Enumerating Collections in Objective-C

One question I often get asked is what’s the best way to enumerate the contents of a collection in Objective-C. I thought I would list them all in this blog post as a reference.

There are four different ways to enumerate a collection in Objective-C. They are listed below in the order I recommend them.

 1. Block-Based Enumeration

Block-based enumeration provides the fastest way to enumerate a collection. Here is an example showing how to enumerate an NSArray:

[array enumerateObjectsUsingBlock:
  ^(id object, NSUInteger index, BOOL *stop) {
    if ([self stopEnumerating]) {
      *stop = YES;
    }
}];

 2. Fast Enumeration

for (id item in collection) {
  // ...
}

 3. NSEnumerator

for (id item in [array reverseObjectEnumerator]) {
  // ...
}

 4. C for Loop

int count = [array count];
for (int index = 0; index < count; index++) {
    id item = [array objectAtIndex:index];
    // ...
}

 An Important Gotcha

Although I recommend that you use the block-based enumeration in almost all cases, there is one scenario where you should avoid it. To understand what that scenario could be, let’s look at the code snippet listed below.

- (NSArray *)articlesFromJson:(NSArray *)json
                        error:(NSError **)error
{
    [json enumerateObjectsUsingBlock:
      ^(NSDictionary *articleJson, NSUInteger index, BOOL *stop) 
    {
        if ([self isJsonInvalid:articleJson
                          error:error])
        {
            *stop = YES;
        }
    }];
}

The articlesFromJson:error: method accepts a pointer to a pointer to an NSError object as a parameter. That error parameter is implictly marked as __autorelease by Clang. Since the enumerateObjectsUsingBlock: method automatically creates an autorelease pool, the error parameter will get destroyed by Objective-C runtime as soon as the enumeration block is done. As a result, if any other code attempts to access the error parameter after the enumeration
is complete, the app will crash because the memory location it points to has become invalid. Therefore in situations like this, I recommend that you use one of the other alternatives listed above.

 Further Exploration

 
3
Kudos
 
3
Kudos

Now read this

Test-Driven Development in Swift

In this blog post, we will learn how to build a simple iOS app menu (shown below) using Test-Driven Development in Swift. Here are things you need to know to fully understand the concepts presented in this post: Xcode 6 Familiarity with... Continue →