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

Why You Should Use NSFetchedResultsController?

NSFetchedResultsController is a very useful class provided by the CoreData framework. It solves many performance issues you frequently run into while reading a large amount of data from database and displaying that data using a... Continue →