Skip to content
Lesson 5 of 6

Step 1 of 5 · Reading · ~2 min

Learn

Collections, Control Flow, Selectors

Foundation provides the standard collection classes. Mostly used as immutable by default; mutable variants exist.

NSArray (immutable)

NSArray *fruits = @[@"apple", @"banana", @"cherry"];
[fruits count]          // 3
fruits[0]                // @"apple" (subscript syntax)
[fruits objectAtIndex:0] // same thing
[fruits firstObject]     // @"apple"
[fruits lastObject]      // @"cherry"
[fruits containsObject:@"banana"]   // YES

The @[...] is array literal syntax. Each element must be an Objective-C object — not a primitive. For numbers: @42 (boxed NSNumber).

NSMutableArray

Mutable variant — explicitly:

NSMutableArray *list = [NSMutableArray array];
[list addObject:@"first"];
[list addObject:@"second"];
[list removeObjectAtIndex:0];
[list insertObject:@"new" atIndex:0];

Or from an immutable: NSMutableArray *m = [array mutableCopy];

NSDictionary

NSDictionary *person = @{
    @"name": @"Ada",
    @"age": @36,
    @"active": @YES
};

NSString *name = person[@"name"];
NSNumber *age = person[@"age"];
int ageInt = [age intValue];
[person count]                  // 3
[person allKeys]                 // NSArray of @"name", @"age", @"active" (order undefined)

NSMutableDictionary

NSMutableDictionary *config = [NSMutableDictionary dictionary];
config[@"theme"] = @"dark";
config[@"size"] = @14;
[config removeObjectForKey:@"theme"];

NSSet / NSMutableSet

Unordered, no duplicates:

NSSet *unique = [NSSet setWithArray:@[@1, @2, @2, @3]];
[unique count]                  // 3 (duplicates collapsed)
[unique containsObject:@2]      // YES

Bounds and cost

objectAtIndex: is constant time — NSArray stores its elements contiguously, so index 0 and index 10,000 cost the same. What it is not is forgiving: an index at or past count raises NSRangeException and, uncaught, terminates the process. It does not return nil the way a missing dictionary key does.

NSArray *fruits = @[@"apple", @"banana"];
if (i < [fruits count]) {
    printf("%s\n", [fruits[i] UTF8String]);   // safe
}
// [fruits objectAtIndex:5];  // NSRangeException — index 5 beyond bounds [0 .. 1]

There is no safeObjectAtIndex: in Foundation. Bound-checking against count before you subscript is the idiom, and it is the reason count shows up so often in Cocoa code.

Iteration

Fast enumeration (chapter previous):

for (NSString *fruit in fruits) {
    printf("%s\n", [fruit UTF8String]);
}

With index:

[fruits enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop) {
    NSLog(@"%lu: %@", idx, obj);
}];

Functional patterns

Objective-C doesn't have native map/filter, but you can use valueForKey and similar tricks:

NSArray *words = @[@"hello", @"world"];
NSArray *upper = [words valueForKey:@"uppercaseString"];
// [@"HELLO", @"WORLD"]

For real functional ops, libraries like Underscore.m add map/filter/reduce.

Why Foundation matters

These collections are everywhere in Cocoa APIs. Whether you're writing iOS apps in Swift or maintaining macOS code, you'll see NSArray/NSDictionary in API signatures constantly.

Swift bridges them automatically: a Swift [String] becomes NSArray * when crossing into ObjC.

Up nextSelectors and Method PointersCollections, Control Flow, Selectors

Discussion

Ask a question, share an insight, or help someone who’s stuck.

Sign in to post a comment or reply.

Loading…