Welcome to part 2 of my series on How To Make iPhone Apps with no programming experience – where we’ll turn even the non-programmer into an iOS developer! Here’s the article index for the entire series in case you missed it.
This time, we’re going to be diving a little deeper into the Objective-C programming language, learning how to control logic flow and introducing some new Apple classes designed to make organizing your data easier. These two topics will enable you to implement some more complex methods.
1. Recap – Variables, Properties and Methods Examples
If you’re not reading part 2 on the same day you read part 1, then this recap will be really helpful to jog your memory!
So in part 1, you learned how to write a bit of Objective-C code already.
Let’s review some of the code that you saw.
Declaring and assigning values to variables:
int stamina = 9;
Performing math operations and assigning the result to variables:
int resultingStamina = 9 - 5;
Let’s show a couple more variable assignment examples:
Declaring an NSString variable and assigning a string value to it, and then assigning another value to it:
NSString *name = @"Spider-Man"; name = @"Hulk";
The “@” symbol in front of the string is necessary to indicate that it’s a string literal, or in other words, a piece of text.
Also notice that once we’ve declared the variable in line 1, we do not have to declare it again to use it in line 2. Once we’ve assigned “Hulk” to the name variable, it’s overwritten the old text so the name variable will now return “Hulk” if you access it.
Declaring a BOOL variable and assigning a value to it:
BOOL isAngry = YES;
Declaring a property
@property (nonatomic, strong) NSString *nameProperty; @property (nonatomic) int numberProperty;
Notice that in the property declaration in line 2, we don’t specify weak and strong. Remember from the last article what strong and weak means? When we’re declaring properties for value type variables, we don’t need to specify the reference mode because it’s not a reference type property!
Assigning a value to an object’s property:
myObject.nameProperty = @"some name"; myObject.numberProperty = 10;
Declaring some methods
// no parameters - (void) doSomethingHeroic; // 1 parameter - (int) fight:(int)enemyStamina; // 2 parameters - (void) increaseStatsWithStamina:(int)stamina andAgility:(int)agility;
Back in the previous article, we talked about methods and how to declare them. We didn’t really talk about declaring methods that require multiple parameters.
Let’s take a look at it!
Line 2 declares a method with no parameters (pretty straight-forward!).
Line 4 declares a method with 1 parameter (you saw this in the previous article).
Line 6 declares a method with multiple parameters.
The format is like this:
– (void) methodName:(variable_type)parameter_name1 labelForParam2:(variable_type)parameter_name2 labelForParam3:(variable_type)parameter_name3
When you declare a method with more than 1 parameter, the subsequent parameters always follow a label, variable type, parameter name format.
So in line 6, stamina and agility are the two parameter names that I would specify in the method implementation if I wanted to access the values in those parameters.
Lets try to implement that method in line 6:
- (void) increaseStatsWithStamina:(int)stamina andAgility:(int)agility { _stamina += stamina; _agility += agility; }
Remember that _stamina and _agility are two private variables we declared in the header file of our Superhero class back in part 1. In lines 3 and 4, we’re taking the value in the parameter and adding it to our superhero’s private variables.
The “+=” operator is additive so the value of stamina parameter gets added to the existing value in _stamina. You can also write “-=” and it would do a subtraction instead. If we had just wrote “=”, then the value in the stamina parameter would replace the value in _stamina.
Onwards with the new stuff!
2. The IF Statement
The IF statement is common to all programming languages and it’s just a way of adding some conditional logic to programming. The simplest way to think about it is that it gives you the ability to tell the compiler, “If this condition is true, then do this. Otherwise, if this other condition is true, then do this. Otherwise if none of the above conditions are true, then do this“.
Here are the various components of an IF statement:
if (condition) { // do some code } else if (condition2) { // do some other code } else { // do some other code }
You can have multiple conditions beyond condition 2. Just add more “else-ifs”. Or if you only have 2 options, you could have just a simple “If-else”
if (condition) { // do some code } else { // do some other code }
Next, let’s look at what we put into the “condition” part of the if statements.
For a condition, we can write statements that would evaluate to TRUE or FALSE. Here are some examples of statements that would evaluate to a BOOL.
// math equality symbols (<, >, ==, !==, >=, <=) if (3 > 1) { // this code will execute } if (1 == 1) { // this code will execute } if (3 != 4) { // this code will execute } if (3+2 > 5) { } else { // this code will execute }
In the examples above, the first three if statements evaluate to TRUE. The if statement in the fourth example is FALSE so the code in the ELSE clause will get executed.
I want to point out the double-equal sign operator. Remember that the equal sign (=) is already used for assigning values to variables. That’s why we have to use the double-equal sign for comparison of value types.
There’s another operator, the exclamation mark (!). This is to denote “not”. So != means “not equal to”. In example three, our if condition reads, “If three is not equal to four”.
Here are some examples of if statements involving NSString type variables.
// string equality if ([mySuperhero.name isEqualTo:@"Hulk"]) { } if (![mySuperhero.name isEqualTo:@"Hulk"]) { }
In example one, we’re asking, “If this mySuperhero’s name property is equal to Hulk”. Notice that we don’t use the double equal sign to do this comparison because == is used to compare value types.
Remember that NSString is a reference type. It refers to an object! So we use a special method of the NSString class called isEqualTo. This method accepts another NSString as a parameter and returns a BOOL specifying if the two strings are equal or not.
In the second example, notice that there is an exclamation mark in front of the method. This changes the if statement to ask “If this mySuperhero’s name property is NOT equal to Hulk”.
Here’s an example using our BOOL property that we defined earlier.
// straight up BOOL variables if (mySuperhero.isAngry) { }
Since our condition is just a BOOL variable, the if statement will depend on if the BOOL variable has a TRUE or FALSE value in it.
Let’s look at some more complex if statements!
// && is the AND operator if (3 < 4 && 3 < 3) { } else { // this code will execute }
You can test multiple conditions in an if statement! Using the && operator, you can ask something like, “if this statement is true AND this statement is true”.
In the code above, the code in the ELSE clause will execute because the 2nd part of the if statement, 3 < 3, is FALSE.
You can chain together as many statements as you want using the AND operator.
Another operator is the OR operator.
// || is the OR operator if (3 < 4 || 3 < 3) { // this code will execute } else { }
If we change the && to ||, the above if statement will be TRUE if at least ONE of the statements evaluates to TRUE. In the example above it’s asking, “if three is less than 4 OR three is less than three”.
You can mix together && and || to form some pretty complicated condition testing!
if ((3 < 4 || 3 < 3) && ([mySuperhero.name isEqualTo:@"Hulk"] || mySuperhero.isAngry)) { }
In the above statement, both of the bracketed statements have to evaluate to TRUE in order for this whole if statement to be execute. (3 < 4 || 3 < 3) has to be TRUE AND ([mySuperhero.name isEqualTo:@”Hulk”] || mySuperhero.isAngry) has to be TRUE.
The if statement is simple but extremely powerful in our coding arsenal because it allows our code to make decisions and act accordingly!
3. SWITCHing The Learning On!
The switch statement is another control structure but it’s closely related to the if statement.
You’ll find that if you have a lot of conditions to test, you might end up with a giant if statement with a whole bunch of else-if statements.
A switch statement is basically the same idea but it’s used for testing a variable against a bunch of “cases”.
The switch statement looks like this:
switch (expression) { case value1: // do some code break; case value2: // do some code break; default: // do some code }
In the above example, the expression is something that evaluates to an integer and your cases (value1, value2 etc) are integers as well. The switch statement will start at the top and then go down the list of cases to see if your expression matches any of the case values.
If it finds a case that matches, it will execute the code in that block and then skip everything else.
If it doesn’t find any cases that matches, it will execute the code in the “default” block.
Here’s an example of a switch statement that has values filled in:
switch (mySuperhero.stamina) { case 10: mySuperhero.greeting = @"I'm healthy as a horse!"; break; case 1: mySuperhero.greeting = @"I'm dying!"; break; default: mySuperhero.greeting = @"I'm doin' alright."; }
In the example above, we’re switching on the value in the stamina property of the mySuperhero object. The switch statement does something different depending on if the value is 10, 1 or something else.
And with that, we move on to loops!
4. FOR And WHILE Loops
Loops are another one of those common programming concepts that exist in one form or another in all programming languages.
Loops give us a way to perform repetitive statements without writing repetitive code.
There are two types of loops at our disposal, The FOR loop which says, “loop and perform this code FOR X number of times” or the WHILE loop which says “loop and perform this code WHILE some condition is TRUE).
Let’s look at the FOR loop first:
for (int i = 0; i < 10; i++) { // do some code }
In the loop above, it’s going to execute the code in between the curly braces 10 times. Let’s break down the for statement.
First there’s the for keyword followed by three distinct parts separated by semi-colons.
The first part in the brackets is the variable declaration and initialization that will be used to keep track of the loop count. In this case we have int i = 0. We could just as easily change the variable name and initial value as well (for example, int k = 9).
In the second part, it tests if the variable we declared in part one is less than 10. If the condition is TRUE, then perform the loop. In the first iteration, the condition is going to be 0 < 10.
The third part actually gets executed after each iteration of the loop. It increments the variable i by 1. ++ is a shorthand to increment an integer by 1. It’s the same thing as writing i = i + 1 or i += 1.
So the first time it loops, the condition will be testing 0 < 10 because we initialized i = 0. In the second iteration, it will test 1 < 10 all the way until it gets to 10 < 10 which evaluates to FALSE and it won’t loop anymore.
The break statement
Sometimes you want to stop the looping if a certain condition is met. There’s a keyword called break which, when executed, will break out of the loop.
For example, with our Superhero class, we may want to replenish his stamina to full when he eats a hot dog but we don’t know what his current stamina is. We could write code like this:
for (int i = 0; i < 10; i++) { // increment stamina by 1 _stamina++; // if stamina is at 10 points, then break if (_stamina == 10) { break; } }
The WHILE loop
Another way to write the previous example would be using a WHILE loop!
while (_stamina < 10) { // increment stamina by 1 _stamina++; }
The format (in the programming world, we use the word “syntax”), is
while (condition) { // execute code }
This will continue loop as long as the condition is TRUE. Notice that if the condition is FALSE in the first place, there won’t even be one loop because it checks the condition first and then runs the loop code.
There’s another way to write the WHILE loop that runs the loop code first and then checks a condition to see if it should loop again. Here it is:
do { // execute code } while (condition)
This way of writing the WHILE loop will guarantee at least one loop because it will execute the loop code first and then check the condition after. Like in the FOR loop, you can still use the break keyword in a WHILE loop.
5. Collections: NSArray, NSSet and NSDictionary
Who doesn’t like collecting things? I’ve collected things all my life: baseball cards, comic books, rocks, stamps, Pogs (remember those?), Magic: the Gathering etc.
But this section about collections is referring to collecting objects into data sets. There are a couple of Apple classes for this purpose that will allow us to organize and work with our collections of objects easily.
NSArray
An array is common to most programming language. It’s a class that contains a collection of objects. Imagine it like a coat check system where you give it a coat and get a number back to identify which hanger your coat is on.
An array is a class where you can store an object at a specific index and later retrieve that object by asking the array to return the element at the given index.
It’s useful for keeping a collection of values or objects together that are related, rather than declaring separate variables for each object you want to keep track of.
The NSArray syntax looks like this:
NSArray *myArray = [[NSArray alloc] init];
Just like instantiating objects of other classes, we use the alloc and init methods. If you have trouble remember what these are, review it here!
That takes care of declaring and initializing the array. Let’s take a look at how to retrieve items with it.
int numItems = myArray.count; Superhero *hero = [myArray objectAtIndex:0];
First of all, the NSArray object has a property called count. This will return the number of items in this collection.
Next, the NSArray is zero based, so the first item will be at index 0. In line 2, we retrieve the element at index 0 and we’re assuming that this array stores a bunch of Superhero objects. I’m declaring a new Superhero variable and assigning it the first item in the collection myArray.
However, there’s something wrong here. Since myArray can store any object, the method objectAtIndex doesn’t return a Superhero object; it returns a generic id object.
The keyword id is used to denote an unknown class. Because the NSArray can store any sort of object, the return type for objectAtIndex of can’t specify any specific class type.
So XCode won’t actually let us assign the object we get from [myArray objectAtIndex:0] into our Superhero *hero variable because they’re not of the same type.
If we know for a fact that the object at index 0 is a Superhero object, then we can use Casting to assign it to the *hero variable.
Casting is a way for us to tell the compiler, “Relax, I know that this object is a instance of [classname], so treat it as such”.
Our revised syntax looks like this:
Superhero *hero = (Superhero*)[myArray objectAtIndex:0];
Ok, now you know how to declare an array, check how many items are in it and retrieve an object at a specific index. How do you put items into the array?
Here’s one way:
NSArray *myArray = [[NSArray alloc] initWithObjects:object1, object2, object3, nil];
The NSArray class has special initialization methods like the one shown above. The initialization method initWithObjects accepts a series of objects that it will use to create and initialize the array with. After that, you’ll have an NSArray object called myArray that has 3 objects.
Notice that there’s a “nil” as the last object? The nil keyword is there to signify the end of the list of objects.
nil is also the value of a reference type variable if you declare it without assigning anything to it. It essentially means nothing.
Superhero *hero; if (hero == nil) { // This code will execute }
In the above example, we declare a variable of type Superhero, but we don’t assign anything to it, so by default, its value is nil and you can see from the if statement that you can check against nil as well.
So now we know how to initialize an NSArray with objects but what if we wanted to add or remove objects from it after creation?
In order to understand that, we first have to talk about mutability!
Mutability
The NSArray class is immutable, which means that it cannot be changed or modified after it’s been created. So after you use the initWithObjects method, you cannot add or remove objects from the array collection.
NSMutableArray
There’s a separate class called NSMutableArray that will allow you to modify it after creation.
Here are methods to add and remove objects for the NSMutableArray class:
NSMutableArray *myMutableArray = [[NSMutableArray alloc] init]; // This adds an object to the end of the array [myMutableArray addObject:object1]; // This inserts an object at a specifc index [myMutableArray insertObject:object2 atIndex:0]; // This returns an object at a specific index [myMutableArray objectAtIndex:0];
If you have a predefined set of objects that you will be working with, then maybe NSArray is for you. It’s less overhead and more secure than NSMutableArray.
If you’re going to be adding to and modifying the collection throughout your code, then use NSMutableArray.
Iterating through an array using loops
Something that you’ll come across often in your coding adventures is the need to loop through each object in your collection of objects and do something to the object.
If you remember earlier when we discussed for loops, you could do something like this:
// Declare our superhero array with 3 heroes NSArray *arrayOfSuperheroes = [[NSArray alloc] initWithObjects:object1, object2, object3, nil]; // Loop through all superheroes in the array for (int i = 0; i < arrayOfSuperheroes.count; i++) { // Retrieve the hero from the array for this iteration of the loop Superhero *hero = (Superhero*)[arrayOfSuperheroes objectAtIndex:i]; // Do something with the superhero }
In the code above, we’re loop through the array contents and in each iteration of the loop, we’re using the variable i to access a new element of the array.
Here’s another way to write the for loop when you need to iterate through a collection.
// Loop through all superheroes in the array for (Superhero *hero in arrayOfSuperheroes) { // Do something with the hero variable }
The above statement is a little cleaner and succinct so if you don’t need a counter variable then you should use this type of syntax. It’s essentially doing the same thing as the for loop that specifies the i variable. The above statement reads, “for each Superhero object in arrayOfSuperheroes”. And you would refer to the current hero for that iteration by using the *hero variable.
NSSet
An NSSet is a collection that you use when you want to store a set of unordered and unique objects.
Here are some initialization methods for NSSet:
NSSet *mySet = [[NSSet alloc] initWithObjects:object1, object2, nil]; NSArray *myArray = [[NSArray alloc] initWithObjects:object1, object2, nil]; NSSet *mySet2 = [[NSSet alloc] initWithArray:myArray];
Just like NSArray, NSSet is immutable and there’s an equivalent NSMutableSet.
When would you use an NSSet versus NSArray? Well, when order doesn’t matter, NSSet offers slightly better performance because of how the objects are referenced behind the scenes. If ordering matters, then stick with an array!
NSDictionary
The NSDictionary class lets you store objects or values with a key and later use the key to retrieve the object or value back.
Think of our earlier coat check example with NSArray, except that this time when you check in a coat, instead of getting a number representing an index, you instead write down some sort of key (could be text or a number) that you can use later to retrieve the coat.
Here’s how you’d declare a dictionary:
NSDictionary *myDictionary = [[NSDictionary alloc] init];
And here’s how you would retrieve an item from the dictionary:
Superhero *hero = (Superhero*)[myDictionary objectForKey:@"Hulk"];
If you pass in a key to objectForKey and there’s no such existing key, then the dictionary will return nil.
NSDictionary is immutable so if you want to add and remove keys after creation, you have to use NSMutableDictionary.
Using a NSMutableDictionary, here’s an example of how to add and remove key-value pairs:
NSMutableDictionary *myMutableDictionary = [[NSMutableDictionary alloc] init]; // Add an object with the key "Hulk" [myMutableDictionary setObject:object1 forKey:@"Hulk"]; // Remove an object with the key "Hulk" [myMutableDictionary removeObjectForKey:@"Hulk"];
Out of the three collection classes, I find myself using arrays the most, followed by dictionaries and then sets.
Let’s Summarize
That was a lot of Objective-C code that we went through today! All useful stuff though, right?
Now you know how to:
-Control logic flow via IF and SWITCH statements!
-Loop using the FOR and WHILE loops!
-Use Arrays, Sets and Dictionaries!
That’s a lot of the Objective-C code that you will most commonly see and use!
What’s Next?
This concludes the iOS app development tutorial. In part 3, we’ll visit the one software design pattern that ALL iPhone and iPad apps are created from. You’re on your way to making awesome iPhone and iPad apps!
Go To Part 3
I want to make this series and this article in particular the best and easiest to understand resource for beginners to learn how to develop iPhone apps. If you’ve got any feedback, good or bad, please let me know via the comments below so I can update parts which are confusing, add more examples and to continue updating this resource.
And if you’ve enjoyed this article or you know someone who might be interested in learning how to build iOS apps, please share this series with them. It’s targeted at the non-programmer (sort of like an iPhone application development for dummies book) so anyone you know will be able to pick this up and progress towards developing iPhone apps!