Read iOS Programming: The Big Nerd Ranch Guide, 3/e (Big Nerd Ranch Guides) Online
Authors: Aaron Hillegass,Joe Conway
Tags: #COM051370, #Big Nerd Ranch Guides, #iPhone / iPad Programming
What exactly is this
NSMutableArray
object you’re using? An array is a collection object (also called a container). The Cocoa Touch frameworks provide a handful of collection objects, including
NSDictionary
and
NSSet
, and each has a slightly different use. An array is an ordered list of objects, and these objects can be accessed by an index. Other languages might call it a list or a vector. An
NSArray
is immutable, which means you cannot add or remove objects after the array is instantiated. You can, however, retrieve objects from the array.
NSArray
’s mutable subclass,
NSMutableArray
, lets you add and remove objects dynamically.
In Objective-C, an array does not actually
contain
the objects that belong to it; instead it holds a pointer to each object. When an object is added to an array,
the address of that object in memory is stored inside the array.
So, to recap, in your command line tool, you created an instance of
NSMutableArray
and added four instances of
NSString
to it, as shown in
Figure 2.7
.
Figure 2.7 NSMutableArray instance
Arrays can only hold references to Objective-C objects. This means primitives and C structures cannot be added to an array. For example, you cannot have an array of
int
s. Also, because arrays hold pointers to objects,
a single array can contain objects of different types
. This is different from most strongly-typed languages where an array can only hold objects of its declared type.
You can ask an array how many objects it is currently storing by sending it the message
count
.
This information is important because if you ask for an object from an array at an index that is greater than the number of objects in the array, an exception will be thrown. (Exceptions are very bad; they will most likely cause your application to crash. We’ll talk more about exceptions at the end of this chapter.)
When an object is added to an array with the message
addObject:
, it is added at the end of the array. You can also insert objects at a specific index – as long as that index is less than or equal to the current number of objects in the array.
Note that you cannot add
nil
to an array. If you need to add
“
holes
”
to an array, you must use
NSNull
.
NSNull
is an object that represents
nil
and is used specifically for this task.
To retrieve the pointer to an object later, you send the message
objectAtIndex:
to the array.
Classes, like
NSMutableArray
, exist in a hierarchy, and every class has exactly one superclass – except for the root class of the entire hierarchy:
NSObject
(
Figure 2.8
). A class inherits the behavior of its superclass, which means, at a minimum, every class inherits the methods and instance variables defined in
NSObject
.
As the top superclass,
NSObject
’s role is to implement the basic behavior of every object in Cocoa Touch. Three of the methods
NSObject
implements are
alloc
,
init
, and
description
. (We sometimes say
“
description
is a method
on
NSObject
”
and mean the same thing.)
Figure 2.8 Class hierarchy
A subclass adds methods and instance variables to extend the behavior of its superclass. For example,
NSMutableArray
extends
NSArray
’s ability to hold pointers to objects by adding the ability to dynamically add and remove objects.
A subclass can also override methods of its superclass. For example, sending the
description
message to an
NSObject
returns the object’s class and its address in memory, like this:
A subclass of
NSObject
can override this method to return something that better describes an instance of that subclass. For example,
NSString
overrides
description
to return the string itself.
NSArray
overrides
description
to return the description of every object in the array.
In this section, you’re going to create a subclass of
NSObject
named
BNRItem
. An instance of the
BNRItem
class will represent an item that a person owns in the real world. To create a new class in
Xcode
, choose
File
→
New
→
New File...
. In the lefthand table of the panel that appears, select
Cocoa
from the
Mac OS X
section. Then select
Objective-C class
from the upper panel and hit
Next
(
Figure 2.9
).
Figure 2.9 Creating a class
On the next panel, name this new class
BNRItem
. Select
NSObject
as the superclass and click
Next
, as shown in
Figure 2.10
.
Figure 2.10 Choosing a superclass
A panel will drop down that prompts you to create the files for this new class (
Figure 2.11
). When creating a new class for a project, you want to save the files that describe it inside the project’s source directory on the filesystem. By default, the current project directory is already selected for you. You can also choose the group in the project navigator that these files will be added to. Because these groups are simply for organizing and because this project is very small, just stick with the default. Make sure the checkbox is selected for the
RandomPossessions
target. This ensures that this class will be compiled when the
RandomPossessions
project is built. Click
Create
.
Figure 2.11 Saving class files
Creating the
BNRItem
class generated two files:
BNRItem.h
and
BNRItem.m
. Locate those files in the project navigator.
BNRItem.h
is the
header file
(also called an interface file). This file declares the name of the new class, its superclass, the instance variables that each instance of this class has, and any methods this class implements.
BNRItem.m
is the implementation file, and it contains the code for the methods that the class implements. Every Objective-C class has these two files. You can think of the header file as a user manual for an instance of a class and the implementation file as the engineering details that define how it really works.
Open
BNRItem.h
in the editor area by clicking on it in the project navigator. The file currently looks like this:
Objective-C retains all the keywords of the C language, and additional keywords specific to Objective-C are distinguishable by the
@
prefix. To declare a class in Objective-C, you use the keyword
@interface
followed by the name of this new class. After a colon comes the name of the superclass. Objective-C only allows single inheritance, so you will only ever see the following pattern:
The
@end
directive indicates that the class has been fully declared.
So far, the
BNRItem
class doesn’t add anything to its superclass
NSObject
. It needs some item-like instance variables. An item, in our world, is going to have a name, a serial number, a value, and a date of creation.
Instance variables for a class are declared in between curly brackets immediately after the class declaration. In
BNRItem.h
, add four instance variables (and the curly brackets that contain them) to the
BNRItem
class:
Now every instance of
BNRItem
has one spot for a simple integer and three spots to hold references to objects, specifically two
NSString
instances and one
NSDate
instance. (A reference is another word for pointer; the
*
denotes that the variable is a pointer.)
Figure 2.12
shows an example of a
BNRItem
instance after its instance variables have been given values.
Figure 2.12 A BNRItem instance
Notice that
Figure 2.12
shows a total of four objects: the
BNRItem
, two
NSString
s, and the
NSDate
. Each of these objects is its own object and exists independently of the others. The
BNRItem
only has pointers to the three other objects. These pointers are the instance variables of
BNRItem
.
For example, every
BNRItem
has a pointer instance variable named
itemName
. The
itemName
of the
BNRItem
shown in
Figure 2.12
points to an
NSString
instance whose contents are
“
Red Sofa.
”
The
“
Red Sofa
”
string does not live inside the
BNRItem
, though. The
BNRItem
instance knows where the
“
Red Sofa
”
string lives in memory and stores its address as
itemName
. One way to think of this relationship is
“
the
BNRItem
calls this string its
itemName
.
”
The story is different for the instance variable
valueInDollars
. This instance variable is
not
a pointer to another object; it is just an
int
. Non-pointer instance variables are stored inside the object itself. The idea of pointers is not easy to understand at first. In the next chapter, you’ll learn more about objects, pointers, and instance variables, and, throughout this book, we will make use of object diagrams like
Figure 2.12
to drive home the difference between an object and a pointer to an object.