Learn to Code iOS Apps 2: Strings, Arrays, Objects and Classes

Mike Jaoudi Mike Jaoudi

This post is also available in: Chinese (Simplified), Korean, Polish

Learn to Code an iPhone App

Learn to Code an iPhone App

Welcome to Part 2 of the Learn to Code iOS Apps series! This series introduces you to the basics of programming with the goal of creating an iOS app; no prior programming experience is required.

In the first tutorial in the series, you learned the basics of programming in Objective-C. Specifically:

  • In Part 1, you learned the basics of Objective-C programming and you created a simple command line number guessing game.
  • In Part 2 (You are Here!), you will learn about objects and classes in Objective-C and you will create a simple app to track people’s names and ages.
  • In Part 3, the real fun begins! Now that you know the basics of programming, you will take all that you’ve learned and create a simple iPhone game of your own.
  • In Part 4, you will take this app and make it beautiful, learning more about customizing the look and feel of iPhone apps.

Welcome to Part 2 of the Learn to Code iOS Apps series! This series introduces you to the basics of programming with the goal of creating an iOS app; no prior programming experience is required.

This part builds on the basic concepts that were covered in Part 1. If you haven’t worked through Part 1 yet and are new to programming or Objective-C, it’s highly recommended that you do so.

In this part you will learn about strings, arrays, classes, and objects in Objective-C. You will create will a Mac OS X app that keeps track of a list of people’s names and ages in order to learn these concepts.

These are fundamental building blocks that you will use in Part 3 of this series when you begin your iOS adventures in earnest and create your very first iPhone app!

Getting Started

This time you’re going to create a completely new project. You’ll choose a OS X command line app so you can continue to focus on the basics. Don’t worry – you’ll make an app with a user interface next time!

Start by launching Xcode and creating a new project by navigating to File\New\Project….

In the left column under OS X click on Application, select Command Line Tool, and click Next, as shown in the screenshot below:

New Project_Annotated

Fill in the project options as follows:

  • Product Name: PeopleDatabase
  • Organization Name: This can be left blank.
  • Company Identifier: Enter com.yourname
  • Type: Foundation
  • Use Automatic Reference Counting: Check this box

When you have finished filling out the information, the dialog should look similar to the one pictured below:

New Project Info

Just as in the previous project, you will add all your code inside the @autoreleasepool block of main.m — right where the comment says insert code here.

Working with Objects

Objective-C is known as an object-oriented language. But what is an object?

You’ve worked with variables containing primitive data types, such as int, which holds an integer value. And that’s it. Primitive types don’t do anything beyond storing a single value.

However, objects extend this model by allowing multiple properties or values. For example, a button object might have a size, a color, and a label. Objects can also perform actions; for example, an image object could resize itself or draw itself on the screen.

Generally the type of an object is not referred to as a type, but rather a class. For example, consider the two following lines of code:

int age = 40;
NSString *name = @"Mike";

In plain language, you would describe age as being “a variable of type int“. However, you would describe name as being “an object of class NSString“, or alternately as “an instance of class NSString“.

Note: Notice that there is a star (*) before the variable name this time. Whenever you create new objects, you always have to put a star when declaring the variable names. You can think of this as meaning “pointer to”, so you can say “name is a pointer to an NSString.”

Now that you understand the terminology, the best way to understand objects and classes is to dive right in and start using them.

Working with Strings

A string is used to store text; it can be a single letter, a word, phrase, or even an entire book’s worth of text!

Look at the NSLog included in main.m:

NSLog(@"Hello World");

In this line of code, @"Hello World!" is a string.

In Part 1 of this series, you printed out the value of an int variable using NSLog. You can also print out strings in the same manner.

Replace the NSLog(@"Hello World"); line with the following two lines of code:

NSString *helloString = @"Hello Variable!";
NSLog(@"%@", helloString);

The first line declares a helloString variable which holds an object of class NSString, which is the basic string class in Objective-C. (Don’t worry about the * character for now; just remember that when you declare an object variable, you need to prefix the variable’s name with an *.)

The second line is the now-familiar NSLog statement. But this time, instead of using %i as the format specifier, you use %@ to specify that you wish to print out a string.

Run your app; the output should say ‘Hello Variable!’.

Note: Why does everything in Objective-C seem to be prefixed with “NS”? When Steve Jobs left Apple in the mid-1980s he started a company called NeXT. NeXT created the Objective-C language along with an operating system called NeXTSTEP.

Objects in Objective-C were prefixed with “NS” — short for NeXTSTEP. When Apple bought NeXT in 1996, they developed OSX and iOS on top of the existing NeXTSTEP frameworks — and almost 20 years later, we’re all still using class names from the NeXT era.

CoolStoryBro

String objects can store more than simple static content. Find the two following lines of code:

NSString *helloString = @"Hello Variable!";
NSLog(@"%@", helloString);

…and replace them with the following code:

int x = 10;
NSString *myString = [NSString stringWithFormat:@"The variable x stores the number %i", x];
NSLog(@"%@", myString);

Take a look at each line of code separately. The first line is pretty straightforward; it assigns a value of 10 to the int variable x.

The second line is a bit more involved. In Objective-C, you tell an object to perform an action by sending it a message. The square brackets indicate that a message will be sent to the receiving object. Inside the square brackets, the message receiver NSString is stated first, followed by the stringWithFormat:message.

The NSString class will receive the message and then see if it knows what stringWithFormat: means. Luckily, the programmers at Apple have included the stringWithFormat: method in NSString. stringWithFormat: simply creates a new string from a format string and some parameters.

A method is a task or operation that you want to execute; it’s a block of code stored somewhere else that you can execute to perform a specific task. Note the colon at the end of the method name stringWithFormat:; everything following the colon is considered an argument to the method call.

Most object-oriented programming languages use the terminology “calling a method on an object” rather than “sending a message to an object”. Many Objective-C programmers use this terminology as well. Unless you want to get really picky, you can consider “calling methods” and “sending messages” to be the same thing.

Finally, the third line simply outputs the formatted myString object to the console.

Run your project, and verify that the output reads as follows:

The variable x stores the number 10

In Part 1, you read in the user’s input using scanf. Sadly, you can’t use scanf to read in a string, as scanf doesn’t work on objects. It works only on primitive datatypes such as:

  • int
  • float
  • BOOL
  • char

What to do?

Technically a string is made up of a sequence of individual characters. So to accept string input, you can read in the sequence of characters and convert it to a string.

Add the following code directly below the line NSLog(@"%@", myString);:

NSLog(@"Please enter a word.");
 
// 1
char cstring[40];
 
// 2
scanf("%s",cstring);
 
// 3
NSString *inputString = [NSString stringWithCString:cstring encoding:1];
 
NSLog(@"You entered the word '%@'", inputString);

Here’s an explanation of the above code, comment by comment:

  1. You declare a variable called cstring to hold 40 characters.
  2. You then tell scanf to expect a list of characters by using the %s format specifier.
  3. Finally, you create an NSString object from the list of characters that were read in.

Run your project; if you enter a word and hit Enter, the program should print out the same word you typed. Just make sure the word is less than 40 characters; if you enter more, you might cause the program to crash — you are welcome to test that out yourself! :]

C-Strings vs. NSString

You might be wondering why you had to convert the contents of cstring to an NSString. A simple list of characters is known as a “C string”. In the C language, which is the predecessor to Objective-C, the only way to store characters is by sticking them in a list. It’s efficient — but a little unwieldy when you want to manipulate that string data.

NSString also stores a C string, but also provides a host of methods that allow you to do things such as get the string’s length and compare it to other strings.

Find the following line in your code:

NSLog(@"You entered the word '%@'", inputString);

…and change it to read as follows:

NSLog(@"You entered the word '%@' and it is %li characters long", inputString, [inputString length]);

Because inputString is an object, it can receive messages such as length, which causes it to report back the length of the string.

Run your app and enter a word. Your console session should look something like the following:

Please enter a word.
objects
You entered the word 'objects' and it is 7 characters long

Declaring an object like NSString is significantly different from declaring a simple primitive variable type. Here is how inputString is declared:

NSString *inputString = [NSString stringWithCString:cstring encoding:1];

NSString *inputString simply creates an NSString object named inputString. The asterisk (*) that precedes the name of the object turns the variable into a pointer. A pointer just stores the memory location of the object — not the object itself. When declaring objects, they are always declared as pointers using the asterisk notation.

Note: Declaring an object pointer does not automatically create the object, which is different from primitive type variables. If you look at the code example above, everything to the right of the equals sign is what creates the object. If you don’t actually create the object that the pointer references, the pointer will literally point to nothing.

Why are pointers necessary? Objects can take up a lot of memory; it’s more efficient and convenient to pass around the memory address to where the object is stored. Otherwise you would be making huge in-memory copies of the object for everyone to use.

The need for pointers when working with objects goes a little deeper, but for now just remember that you always refer to objects through pointers.

Working with Classes and Objects

Your next task will be to create a simple database that keeps track of names and ages by using objects and custom classes.

To start, clear out everything in the @autoreleasepool code block. The code in main.m should look like the following:

#import <Foundation/Foundation.h>
 
int main(int argc, const char * argv[])
{
    @autoreleasepool {
 
    }
    return 0;
}

Think for a moment about how you will store each person’s record. It needs to contain their first name, their last name, and their age. Three pieces of data, all stored together — it sounds like a great use for an object, doesn’t it?

But there’s no predefined “Person” class in Objective-C. However, you can create your very own custom objects by defining a new class. A class is essentially a blueprint to say how an object should look and behave.

First, you’ll need to create a new file to hold your new class. In Xcode, navigate to File\New\File…, as shown below:

FileMenu

In the left column under OS X, select Cocoa. Then select Objective-C Class and click Next.

ObjectiveCClass

Set the class name to Person and the Subclass to NSObject. Click the Next button and then click Create, as illustrated below:

NamePerson

In the file navigator on the left, you should see two new files: Person.h and Person.m.

Person.h is a rather small file. Open it; it will look like the following:

#import <Foundation/Foundation.h>
 
@interface Person : NSObject
 
@end

All files with the .h file extension are called header files. A header file tells the rest of the program about the elements in your class, such as variables and methods. The various portions of the header file are explained as below.

#import <Foundation/Foundation.h>

This is an import statement, which you’ve seen before. It simply imports the basic Foundation class which your app requires.

@interface Person : NSObject

The above line informs the rest of the program that you are making a class called Person. The colon indicates that you are creating a subclass and the NSObject part indicates the class you are subclassing from. NSObject is a basic Objective-C class which can be used to represent an object. It has a few methods and properties which can prove useful in many different scenarios.

But you might be wondering what subclassing is. Subclassing is a way to derive a new class based on an existing class. The new class inherits all the existing attributes of the superclass (that’s the name given to the original class) but it can also define new attributes.

@end

The last line indicates that you are done defining the class. Everything between the @interface line and the @end line describes what is contained in the class.

Working with Instance Variables and Methods

Your Person class needs to store three different things: the first name and last name will be strings, and the age will be an integer. Modify the @interface block as shown below:

@interface Person : NSObject {
  NSString *firstName;
  NSString *lastName;
  int age;
}

The curly braces surround the instance variables of the object. Each Person object in your app has their own distinct set of data; they definitely don’t share names and ages! Instance variables store the individual characteristics of each object. Class variables, on the other hand, are shared amongst all objects of a particular class.

That takes care of storing a person’s data. Now what methods should your Person class have? At a minimum, you’ll need to set and retrieve the person’s information.

Add these lines right above the @end line:

- (void)enterInfo;
- (void)printInfo;

This defines the methods that your class provides to set the person’s data — enterInfo — and to print the person’s data — printInfo. You don’t need to flesh out the methods here in the header file; you just need to declare that they exist.

What does (void) mean before each of these method declarations? Recall that int main states that the return value of main is of type int. (void) indicates that these methods don’t return anything to the caller.

That does it for the header file. Now open Person.m. The file should look like this:

#import "Person.h"
 
@implementation Person
 
@end

This is the implementation file where the source code for your class lives. Looking at the file line-by-line, you will see the following:

#import "Person.h"

This imports the class declarations from your header file, in exactly the same way that you imported the Foundation classes in the header file.

@implementation Person

This indicates the start of the implementation block that contains the meat of your class.

@end

This simply indicates the end of the @implementation block.

That implementation file looks pretty empty. Time to add some code! Add the following code after the @implementation line:

- (void)enterInfo {
    NSLog(@"What is the first name?");
    char cstring[40];
    scanf("%s", cstring);
 
    firstName = [NSString stringWithCString:cstring encoding:1];
 
    // more code for the other fields to come later...
 
}
 
- (void)printInfo {
    NSLog(@"First name: %@", firstName);
}

The two methods above should look pretty familiar. enterInfo will prompt the user to enter a first name and then store it in the firstName instance variable. printInfo uses the familiar NSLog call to print out the stored first name.

This is a good time to test your class by calling it from the main function. Open main.m and add the following line to the top of the file, immediately underneath the #import line::

#import "Person.h"

By importing Person.h, you’ve told main about the existence of your new Person class.

Now add the following code just after the @autoreleasepool line:

Person *newPerson = [[Person alloc] init];
 
[newPerson enterInfo];
[newPerson printInfo];

The first line in the code above creates a new Person object. You’ll see the alloc / init combination a lot in Objective-C; alloc allocates memory for the object, while init creates and initializes the object that will live at that memory address.

The next two lines send messages that call your new methods. The program will first ask the user to enter a first name and then print it back out to the console.

Run your project, and when prompted, enter a first name. Your console output should look similar to the following:

What is the first name?
Michelle
First name: Michelle

Hey, it looks like your object is working as designed! Now you just need to flesh out the rest of the implementation.

Open Person.m, and add the following lines below the comment // more code for the other fields to come later...:

NSLog(@"What is %@'s last name?",firstName);
scanf("%s",cstring);
lastName = [NSString stringWithCString:cstring encoding:1];
 
NSLog(@"How old is %@ %@?", firstName, lastName);
scanf("%i", &age);

The code above prompts for the person’s last name and age and stores the data in the matching instance variables.

Finally, replace the printInfo method’s NSLog line with the following:

NSLog(@"%@ %@ is %i years old", firstName, lastName, age);

Run your project, and enter some data when prompted. Your output should look similar to the following:

What is the first name?
Jane
What is Jane's last name?
Smith
How old is Jane Smith?
23
Jane Smith is 23 years old

The Person object is doing exactly what you would expect. However, the app only stores information for one person. That’s not too useful; you need to allow the user to enter information for as many people as they would like.

Working with Sets of Objects

Think back to Part 1 — how did you solve this problem in your Higher and Lower game? Ah — you can use a looping structure to repeat the same bits of code until the user is done.

Replace the code in the @autoreleasepool block in main.m with the following:

  @autoreleasepool {
    char response;
 
    do {
      Person *newPerson = [[Person alloc] init];
 
      [newPerson enterInfo];
      [newPerson printInfo];
 
      NSLog(@"Do you want to enter another name? (y/n)");
      scanf("\n%c", &response);
    } while(response == 'y');
 
  }

With this new code, in addition to asking for the name and age data, the program will now prompt the user to indicate if they are done. response can holds either a ‘y’ or ‘n’, depending on the user’s response.

You may have noticed that this while loop looks a little different than the one you used in Part 1. That’s because this is known as a do-while loop. The only difference here is that the looping condition is checked at the end of the loop, instead of at the beginning. This means that the code inside the loop will always execute at least once, regardless of the state of the looping condition.

Take a close look at the scanf statement in the above code. There’s a strange “\n” in there. What does that mean?

\n stands for “newline”, or the character that is printed when you hit the Enter key. It’s not a visible character, but scanf will still pick it up when it parses the user’s input. So \n%c is a special format specifier that tells scanf to read in a character discarding newlines and other whitespace characters such as a space or tab.

The looping condition at the end of the block checks if response is equal to the character ‘y’; if so, it loops back around. Note that the while condition has a semicolon after it; this is the only type of loop that requires a semicolon.

Run your project, and enter a few names and ages. As long as you keep typing “y”, the program will let you add another person. However, none of the names are being stored. Each time you go through the loop, a new Person object is created and the previous one is lost.

How do you go about storing multiple Person objects to retrieve later? You don’t want variables called person1, person2, person3, and so on — you have no idea how many you’ll need. Instead, you need to store them in some kind of list. To do that, you’ll use an array.

Working with Arrays

Arrays are a way of storing a bunch of objects in a list. There are two types of arrays in Objective-C: NSArray and NSMutableArray. NSArray is a basic static array; once you have created the array, you can’t add or remove items from it. This type of array is immutable, or unchangeable, much like many objects in Objective-C.

Conversely, NSMutableArray lets you add and remove items at any time. Since you will be adding an indeterminate number of people to the array over time, an NSMutableArray is a good choice in this situation.

Find the line that declares the response variable in main.m and add the following line directly below it:

NSMutableArray *people = [[NSMutableArray alloc] init];

The above line allocates and initializes a new NSMutableArray object called people.

Add the following line of code directly below the [newPerson printInfo]; line:

[people addObject:newPerson];

addObject: is a method of NSMutableArray that lets you add objects to the array. Now, each time you create a new Person object, you don’t have to worry about it disappearing — you simply add it to your people array so that it will remain in memory.

The storage mechanism of NSMutableArray is demonstrated by the image below:

DataLayout

That solves the problem of storing the Person objects — but how do you retrieve the objects once they’re stored? If you know the specific position, or index of the object in the array, you can reference the object by its index, as follows:

Person *theFirstPerson = people[0]

That code retrieves the first person in the array. Why are you using index “0″ instead of “1″, you ask? Computers generally start indexing lists at zero, so the first element in the array is at position 0, the second element is at position 1, and so on.

In your app, you will loop through the array and print out all the stored names and ages only when the user has finished entering all of the data. This time you won’t use a while or do-while loop — you’ll be using a for loop.

Add the following code after the line while (response == 'y');:

NSLog(@"Number of people in the database: %li", [people count]);
for (Person *onePerson in people) {
  [onePerson printInfo];
}

The NSLog line will print out the number of Person objects stored in the array using the count property of NSMutableArray.

The for loop starts at the beginning of the array and executes the code contained in the curly braces for each object found in the array. This is pretty handy, since now you really don’t need to know beforehand how many Person objects might be stored in the array.

Finally, the printInfo method of your Person object is used to print out each person’s information.

Run your project, and enter some information for a few people. When you are finished, the program will then neatly print out all of the people that you have stored in the array. Here’s a sample run of the program:

What is the first name?
John
What is John's last name?
Appleseed
How old is John Appleseed?
23
John Appleseed is 23 years old
Do you want to enter another name? (y/n)
y
What is the first name?
Albert
What is Albert's last name?
Einstein
How old is Albert Einstein?
76
Albert Einstein is 76 years old
Do you want to enter another name? (y/n)
n
Number of people in the database: 2
John Appleseed is 23 years old
Albert Einstein is 76 years old

Where To Go From Here?

In this short tutorial, you have covered a fair bit of ground, including some rather complicated concepts in Objective-C:

  • do-while loops
  • for loops
  • Classes
  • Objects
  • Header files
  • Implementation files
  • Arrays

The best way to really understand Objective-C is to play around with your own code! Break it apart, add some more pieces, and put it back together; experimenting (and fixing things that you broke while experimenting) is the best way to learn how to program.

The final project with full source code can be found here.

Check out the next tutorial in the series, where you’ll put everything you learned so far to use, and create your first actual iPhone app!

If you have any questions or comments, feel free to raise them in the forums.

Mike Jaoudi
Mike Jaoudi

Mike Jaoudi is a Computer Science major at New York University. For the past couple of years, Mike also worked as an Instructor and Curriculum Developer at iD Tech Camps for iOS App Design and iOS Game Design. While at iD Tech, Mike discovered an enjoyment for teaching, as he’s found that “when you teach you learn twice”. He is a fan of the BBC show “Sherlock” and NCAA fencer. Check out his multiplayer snake game, Snakez. You can find Mike on Twitter .

User Comments

23 Comments

[ 1 , 2 ]
  • **********
    NSLog(@"Number of people in the database: %li", [people count]);
    for (Person *onePerson in people) {
    [onePerson printInfo];
    }
    ********
    Hi, could you tell me how *oneperson works,
    is it a predefined and does the programme automatically know just "one" object at a time ??
    NSSam
  • Hello,
    first of all, thanks for the tuts.
    now question: how would i implement a first and second firstName and or secondName? if I type in, for instance, fabian adrian the app exits.
    Thanks
    fgeraci
  • Is there a reason why the console will not take "y" as a command to enter another name? I get the error, "'y' is not a valid command." every time. However, I can enter "n," which will stop the program.

    Thank you
    jgstewart
  • What is the advantage of a class compared to just a variable in this particular case? Couldn't you just create the variables "firstName", "lastName" and "age"?
    revil4
  • NSSam: Think of it as: for each object in Array People
    So you create a pointer to an object of type Person, and increment through the array , getting the details of each Person in the array.

    So you declare that you want to progress through the array one person size at a time.

    Hope this helps.
    Danielk
  • fgeraci: Add to Person.h a line:

    NSString *secondName;

    In Person.m implement the input of the string from the console, and then edit the printInfo function to utilise new variable.

    now, implement the logic to handle empty input field and to skip printing of an empty second name field :D
    Danielk
  • hello sir
    for (Person *onePerson in people) {
    [onePerson printInfo];
    can you please explain this part
    i cant understand *onePerson in people
    i hope you reply me asap
    dmthanki12@gmail.com
  • dmthanki12:

    for (Person *onePerson in people) {
    [onePerson printInfo];

    For each pointer of size Person that we shall call onePerson, in the array people
    print out information for that onePerson
    Danielk
[ 1 , 2 ]

Other Items of Interest

Ray's Monthly Newsletter

Sign up to receive a monthly newsletter with my favorite dev links, and receive a free epic-length tutorial as a bonus!

Advertise with Us!

Hang Out With Us!

Every month, we have a free live Tech Talk - come hang out with us!


Coming up in May: Procedural Level Generation in Games with Kim Pedersen.

Sign Up - May

Coming up in June: WWDC Keynote - Podcasters React! with the podcasting team.

Sign Up - June

Vote For Our Next Book!

Help us choose the topic for our next book we write! (Choose up to three topics.)

    Loading ... Loading ...

Our Books

Our Team

Tutorial Team

  • Julian Meyer
  • Felipe Laso Marsetti

... 55 total!

Editorial Team

... 22 total!

Code Team

  • Orta Therox

... 1 total!

Translation Team

  • Heejun Han
  • Cosmin Pupaza
  • Di Peng

... 38 total!

Subject Matter Experts

... 4 total!