Objective-C enumerateUsingBlock vs快速枚举?
以下两种方法的优缺点是什么:
enumerateUsingBlock
NSArray *myArray = [[NSArray alloc] init]; [myArray enumerateObjectsUsingBlock:^(id anObject, NSUInteger idx, BOOL *stop) { if (anObject == someOtherObject) { [anObject doSomething:idx]; *stop = YES; } }];
快速枚举
NSArray *myArray = [[NSArray alloc] init]; int idx = 0 for (id anObject in myArray) { if (anObject == someOtherObject) { [anObject doSomething:idx]; break; } ++idx; }
这个博客文章涵盖了主要的区别。 综上所述:
- 快速枚举可用OS X 10.5+,块可用10.6+
- 对于简单的枚举,快速枚举比基于块的枚举要快一些
- 使用基于枚举的枚举进行并发或反向枚举比使用快速枚举更容易(也更高效)
- 当枚举一个
NSDictionary
你可以用一个基于块的枚举器在一个命中中获得键和值,而使用快速枚举你必须使用该键来检索单独的消息发送中的值。
关于最后一点(NSDictionary枚举),比较一下:
for (id key in dictionary) { id obj = [dictionary objectForKey: key]; // do something with key and obj }
对此:
[dictionary enumerateKeysAndObjectsUsingBlock: ^(id key, id obj, BOOL *stop) { // do something with key and obj }];
此外,这两种方法保护枚举循环内的可变集合不受突变影响。 有趣的是,如果你尝试在一个基于块的枚举中改变集合,你会得到一个由CoreFoundation的__NSFastEnumerationMutationHandler
引发的exception,提示有一些通用的代码。
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"]; }];
输出:
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"
首先想到的是我的想法
-
块在iOS 4及更高版本中可用,所以如果您需要支持旧版本,则无法使用块语法。
-
他们是非常相同的,他们做的除了你不能不小心搞乱块版本的计数器。
-
另一个潜在的区别是,你可以在其他地方定义块,并根据你的状态通过不同的块。
希望这只是一个非常粗略的例子,因为代码片段非常糟糕,并且有更高效的方法来执行此操作;)