Consider:
- (void) testing {
NSMutableArray * numbers = [NSMutableArray arrayWithCapacity:10000000] ;
for (int i = 0 ; i < 10000000 ; ++i) {
[numbers addObject:@(i)] ;
}
NSInteger (^sum)(NSInteger, NSInteger) = ^(NSInteger running, NSInteger n) {
return running + n ;
} ;
double start = ::CACurrentMediaTime() ;
__block NSInteger running = 0 ;
for (NSNumber * n in numbers) {
running = sum(running, [n integerValue]) ;
}
running = 0 ;
double end1 = ::CACurrentMediaTime() ;
[numbers enumerateObjectsUsingBlock:^(NSNumber * n, NSUInteger idx, BOOL *stop) {
running = sum(running, [n integerValue]) ;
}] ;
double end2 = ::CACurrentMediaTime() ;
::NSLog(@"fastEnum: %0.3f, enumUsingBlock: %0.3f", end1-start, end2-end1) ;
}
This outputs:
2013-08-05 00:38:34.852 WC[48299:a0b] fastEnum: 0.341, enumUsingBlock: 1.358
This says that enumerateObjectsUsingBlock
is 4x slower or so than regular iteration.
When does one use one or the other?
What is the "added value" that enumerateObjectsUsingBlock
provides that justifies its cost?
Mattt Thompson wrote a great post on NSHipster about the many ways to iterate with Objective-C.
The added value that enumerateObjectsUsingBlock
provides is giving the index of the object and NSEnumerationOptions
:
enum {
NSEnumerationConcurrent = (1UL << 0),
NSEnumerationReverse = (1UL << 1),
};
typedef NSUInteger NSEnumerationOptions;
Quoting Mattt:
Unless you actually need the numerical index while iterating, it's almost always faster to use a for/in NSFastEnumeration loop instead.
(...)
Again, fast enumeration is almost certain to be much faster than block enumeration, but these options may be useful if you're resigned to using blocks.