Although this question is old, things have not changed, the accepted answer is incorrect.
The enumerateObjectsUsingBlock
API was not meant to supersede for-in
, but for a totally different use case:
- It allows the application of arbitrary, non-local logic. i.e. you don’t need to know what the block does to use it on an array.
- Concurrent enumeration for large collections or heavy computation (using the
withOptions:
parameter)
Fast Enumeration with for-in
is still the idiomatic method of enumerating a collection.
Fast Enumeration benefits from brevity of code, readability and additional optimizations which make it unnaturally fast. Faster than a old C for-loop!
A quick test concludes that in the year 2014 on iOS 7, enumerateObjectsUsingBlock
is consistently 700% slower than for-in (based on 1mm iterations of a 100 item array).
Is performance a real practical concern here?
Definitely not, with rare exception.
The point is to demonstrate that there is little benefit to using enumerateObjectsUsingBlock:
over for-in
without a really good reason. It doesn't make the code more readable... or faster... or thread-safe. (another common misconception).
The choice comes down to personal preference. For me, the idiomatic and readable option wins. In this case, that is Fast Enumeration using for-in
.
Benchmark:
NSMutableArray *arr = [NSMutableArray array];
for (int i = 0; i < 100; i++) {
arr[i] = [NSString stringWithFormat:@"%d", i];
}
int i;
__block NSUInteger length;
i = 1000 * 1000;
uint64_t a1 = mach_absolute_time();
while (--i > 0) {
for (NSString *s in arr) {
length = s.length;
}
}
NSLog(@"For-in %llu", mach_absolute_time()-a1);
i = 1000 * 1000;
uint64_t b1 = mach_absolute_time();
while (--i > 0) {
[arr enumerateObjectsUsingBlock:^(NSString *s, NSUInteger idx, BOOL *stop) {
length = s.length;
}];
}
NSLog(@"Enum %llu", mach_absolute_time()-b1);
Results:
2014-06-11 14:37:47.717 Test[57483:60b] For-in 1087754062
2014-06-11 14:37:55.492 Test[57483:60b] Enum 7775447746