Objective-C enumerateUsingBlock vs fast enumeration?

What are the advantages and disadvantages of the following two approaches:

enumerateUsingBlock

NSArray *myArray = [[NSArray alloc] init]; [myArray enumerateObjectsUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop) { if (anObject == someOtherObject) { [anObject doSomething:idx]; *stop = YES; } }];

fast enumeration

NSArray *myArray = [[NSArray alloc] init]; int idx = 0 for (id anObject in myArray) { if (anObject == someOtherObject) { [anObject doSomething:idx]; break; } ++idx; }

-------------Problems Reply------------

This blog post covers the major differences. In summary:

  • Fast enumeration is available on OS X 10.5+, blocks are available on 10.6+
  • For simple enumeration, fast enumeration is a bit faster than block-based enumeration
  • It's easier (and more performant) to do concurrent or reverse enumeration with block-based enumeration than with fast enumeration
  • When enumerating over an NSDictionary you can get key and value in one hit with a block-based enumerator, whereas with fast enumeration you have to use the key to retrieve the value in a separate message send.

Regarding the last point (NSDictionary enumeration), compare this:

for (id key in dictionary)
{
id obj = [dictionary objectForKey: key];
// do something with key and obj
}

to this:

[dictionary enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) {
// do something with key and obj
}];

In addition, both methods protect mutable collections from mutation inside the enumeration loop. Interestingly, if you try to mutate the collection inside a block-based enumeration, you get an exception thrown by CoreFoundation's __NSFastEnumerationMutationHandler, suggesting that there's some common code under the hood.

NSMutableArray *myArray = [NSMutableArray arrayWithObjects:@"a", @"b", nil];
[myArray enumerateObjectsUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop) {
// Attempt to mutate the array during enumeration
[myArray addObject:@"c"];
}];

Output:

2011-12-14 22:37:53.716 Untitled[5809:707] *** Terminating app due to uncaught exception 'NSGenericException', reason: '*** Collection <__NSArrayM: 0x109614190> was mutated while being enumerated.'
*** First throw call stack:
(
0 CoreFoundation 0x00007fff8cca7286 __exceptionPreprocess + 198
1 libobjc.A.dylib 0x00007fff8319ad5e objc_exception_throw + 43
2 CoreFoundation 0x00007fff8cd311dc __NSFastEnumerationMutationHandler + 172
3 CoreFoundation 0x00007fff8cc9efb4 __NSArrayEnumerate + 612
4 Untitled 0x00000001094efcea main + 250
5 Untitled 0x00000001094efbe4 start + 52
6 ??? 0x0000000000000001 0x0 + 1
)
terminate called throwing an exceptionRun Command: line 1: 5809 Abort trap: 6 ./"$2"

First thoughts that come to my mind

  • Blocks are available in iOS 4 and later so if you need to support older versions then you can not use the block syntax.
  • They are pretty equivalent in terms of what they do apart from you can't accidentally mess up the counter in the block version.
  • One other potential difference is that you can define the block elsewhere and pass in different blocks dependant on your state.

Hopefully this was just a very rough example as the code snippet is pretty poor and there are more efficient way of doing this ;)

Category:objective c Views:1 Time:2011-12-14
Tags: objective c

Related post

  • Objective c "for each" (fast enumeration) - evaluation of collection? 2010-10-07

    It seems from experimentation that the collection expression is evaluated only once. Consider this example: static NSArray *a; - (NSArray *)fcn { if (a == nil) a = [NSArray arrayWithObjects:@"one", @"two", @"three", nil]; NSLog(@"called"); return a;

  • Access previous object/item when using fast enumeration? 2011-03-02

    Simple question, if your iterating through a list of objects using fast enumeration is there a quick way to refer to the previous object so you have (object and object-1)? for(FuzzyThing *thisThing in allThings) { int thisValue = [thisThing value]; /

  • Does fast enumeration in Objective-C guarantee the order of iteration? 2010-05-06

    Can I expect it to go from the start of an array to the end in order? Can't find anything in the docs about this. i.e. is for (id val in array) { NSLog(@"%@", val); } always going to print out the same as for (int i = 0; i < [array count]; ++i) {

  • Fast Enumeration on NSArray of Different Types 2011-12-09

    I have this question here (as well other quesrtions on SO), and the Apple docs about Objective-C collections and fast enumeration. What is not made clear is if an NSArray populated with different types, and a loop is created like: for ( NSString *str

  • Objective-C 2.0 and Fast Enumeration throwing exceptions 2009-02-16

    I have a block of code which is similar to the following: for (NSDictionary *tmp in aCollection) { if ([[bar valueForKey:@"id"] isEqualToString:[tmp valueForKey:@"id"]]) { break; } else { [aCollection addObject:bar]; } } Is this technically an except

  • How does Fast Enumeration (looping) work in Objective-C? (ie: for (NSString *aString in aDictionary)-) 2009-08-21

    I'm working on implementing a customized searchBar for a fairly complex table and have come across this code pattern AGAIN. This is a sample from the Beginning iPhone Development book: - (void)handleSearchForTerm:(NSString *)searchTerm { NSMutableArr

  • fast enumeration on NSDictionary fails with "[Waypoint countByEnumeratingWithState:objects:count:]: unrecognized selector sent to instance -" 2010-01-15

    I have my data in a NSDictionary object where the keys are CGPoints converted to NSValues and the objects are UIColors. Here's the method I'm using to return an object from the dictionary: - (UIColor*) getTemperatureColor2 { NSDictionary* temperature

  • Objective C: Last object when using Fast Enumeration? 2010-12-27

    What is the best way to know when I have reached the last object in an array when using fast enumeration? Is there a better way than incrementing an int and then comparing that to the length of the array? --------------Solutions------------- If you a

  • Objective-C Fast Enumeration Bubble Sort 2011-02-09

    I'm trying to integrate some GCD into my code, and have found that a severe bottleneck is a bubble comparison I am performing between objects in a large array. Here is the original code: NSUInteger count = [arrayToDoWorkOn count]; for (int i = 0; i

  • Fast Enumeration Vs NSEnumerator in Objective-C 2011-03-02

    I have seen this over and over, why exactly is it faster to use fast enumeration in loops rather than an NSEnumerator using nextObject:. --------------Solutions------------- NSEnumerator is the old way to enumerate over collections. It involves creat

  • Objective-C - fast enumeration on a subset of an array? 2011-06-11

    Is there a simple way to do fast enumeration on a range of objects in an array? Something like... for (Object *object in myArray startingAtIndex:50) { //do stuff } ...to avoid having to do something like this... for (Object *object in myArray) { NSUI

  • Setting an object during fast enumeration problems 2011-10-07

    A day or so ago I posted this question: Confused about enumeration... How do I change the objects that during enumeration? I learned that I can call methods on an object during enumeration, but if I assign using the "=" operator then it creates a new

  • Fast enumeration over nil object 2011-10-21

    What should happen here? Is it safe? NSArray *nullArray=nil; for (id obj in nullArray) { // blah } More specifically, do I have to do this: NSArray *array=[thing methodThatMightReturnNil]; if (array) { for (id obj in array) { // blah } } or is this f

  • Objective C fast enumeration trouble 2012-03-04

    I am trying to use fast enumeration to print all songs that are in a playlist, but it seems like I am doing it wrong. Could someone help me out? I have defined a Song class like this : @interface Song : NSObject @property (nonatomic,strong) NSString

  • Cocoa NSArray/NSSet: -makeObjectsPerformSelector: vs. fast enumeration 2009-02-24

    I want to perform the same action over several objects stored in a NSSet. My first attempt was using a fast enumeration: for (id item in mySetOfObjects) [item action]; which works pretty fine. Then I thought of: [mySetOfObjects makeObjectsPerformSele

  • Fast Enumeration With enumeratorAtPath? 2009-12-09

    Are there any issues I may be missing using fastEnumeration with the enumerator below? I only ask as code examples (online & books) always seem to use a whileLoop. The code sniped works fine, just curious if I am missing a potential issue. Please

  • Is fast enumeration considered bad form or is it generally accepted? 2010-01-10

    Just wondering, it seems like it works pretty well but I want to make sure I am using generally accepted coding practices and not get into bad habits. Thanks, Nick --------------Solutions------------- Yes, it's good form. It was introduced as the pre

  • Fast Enumeration With an NSMutableArray that holds an NSDictionary 2010-02-19

    Is it possible to use fast enumeration with an NSArray that contains an NSDictionary? I'm running through some Objective C tutorials, and the following code kicks the console into GDB mode NSMutableArray *myObjects = [NSMutableArray array]; NSArray *

  • Is Fast Enumeration messing with my text output? 2010-05-18

    Here I am iterating through an array of NSDictionary objects (inside the parsed JSON response of the EXCELLENT MapQuest directions API). I want to build up an HTML string to put into a UIWebView. My code says: for (NSDictionary *leg in legs ) { NSStr

Copyright (C) dskims.com, All Rights Reserved.

processed in 0.372 (s). 11 q(s)