Like NSString, NSArray is another class that Objective-C programmers use a lot. An instance of NSArray holds a list of pointers to other objects. For example, let’s say you want to make a list of three NSDate objects and then go through the list and print each date.
Create a new project : a Foundation Command Line Tool called DateList. Open main.m and change the main() function:
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // Create three NSDate objects NSDate *now = [NSDate date]; NSDate *tomorrow = [now dateByAddingTimeInterval:24.0 * 60.0 * 60.0]; NSDate *yesterday = [now dateByAddingTimeInterval:-24.0 * 60.0 * 60.0]; // Create an array containing all three (nil terminates the list) NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday, nil]; // How many dates are there? NSLog(@"There are %lu dates", [dateList count]); // Print a couple NSLog(@"The first date is %@", [dateList objectAtIndex:0]); NSLog(@"The third date is %@", [dateList objectAtIndex:2]); } return 0; }
NSArray has two methods, shown in this example, that you will use all the time:
Arrays are ordered, and you access an item in the array by its index. Arrays are zero-based: the first item is stored at index 0, the second item is stored at index 1, and so on. Thus, if the count method says there are 100 items in the array, you can use objectAtIndex: to ask for the objects at indices 0 to 99.
Figure 15.1 is an object diagram of your program. Notice that the instance of NSArray has pointers to the NSDate objects.
Thus, if you want to loop and process each item in the array (or “iterate over the array”), you can create a for-loop. Edit main.m:
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // Create three NSDate objects NSDate *now = [NSDate date]; NSDate *tomorrow = [now dateByAddingTimeInterval:24.0 * 60.0 * 60.0]; NSDate *yesterday = [now dateByAddingTimeInterval:-24.0 * 60.0 * 60.0]; // Create an array containing all three (nil terminates the list) NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday, nil]; NSUInteger dateCount = [dateList count]; for (int i = 0; i < dateCount; i++) { NSDate *d = [dateList objectAtIndex:i]; NSLog(@"Here is a date: %@", d); } } return 0; }
Programmers do this so often that they made a special addition to the for-loop for iterating over arrays. Edit the code to use this mechanism:
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // Create three NSDate objects NSDate *now = [NSDate date]; NSDate *tomorrow = [now dateByAddingTimeInterval:24.0 * 60.0 * 60.0]; NSDate *yesterday = [now dateByAddingTimeInterval:-24.0 * 60.0 * 60.0]; // Create an array containing all three (nil terminates the list) NSArray *dateList = [NSArray arrayWithObjects:now, tomorrow, yesterday, nil]; for (NSDate *d in dateList) { NSLog(@"Here is a date: %@", d); } } return 0; }
This type of loop is known as fast enumeration, and it is an extremely efficient way to walk through the items in an array. There is one restriction: you may not add to or remove from the array while enumerating over it.
Arrays come in two flavors:
An instance of NSArray is created with a list of pointers. You can never add or remove a pointer from that array.
An instance of NSMutableArray is similar to an instance of NSArray, but you can add and remove pointers. (NSMutableArray is a subclass of NSArray. More about subclasses in Chapter 18.)
Change your example to use an NSMutableArray instance and methods from the NSMutableArray class:
#import <Foundation/Foundation.h> int main(int argc, const char * argv[]) { @autoreleasepool { // Create three NSDate objects NSDate *now = [NSDate date]; NSDate *tomorrow = [now dateByAddingTimeInterval:24.0 * 60.0 * 60.0]; NSDate *yesterday = [now dateByAddingTimeInterval:-24.0 * 60.0 * 60.0]; // Create an empty array NSMutableArray *dateList = [NSMutableArray array]; // Add the dates to the array [dateList addObject:now]; [dateList addObject:tomorrow]; // Put yesterday at the beginning of the list [dateList insertObject:yesterday atIndex:0]; for (NSDate *d in dateList) { NSLog(@"Here is a date: %@", d); } // Remove yesterday [dateList removeObjectAtIndex:0]; NSLog(@"Now the first date is %@", [dateList objectAtIndex:0]); } return 0; }