当 Apple 推出快速枚举时,我在 WWDC,并且(我记得)当时我们被告知右手对象被移动到临时对象中。此外,它必须是因为这有效:
for(id foo in [myCollection reverseObjectEnumerator])
您可以看到执行快速枚举的集合采用“快速枚举协议”(NSFastEnumeration),它有一种方法:
– countByEnumeratingWithState:objects:count:
该方法返回一个 C 对象数组,它可以让枚举非常快速地进行,再次支持右侧的一次性使用。
现在,说了这么多,目前 Apple 建议开发人员(在 WWDC)使用块枚举,他们声称这既更快又生成更少的代码:
[myCollection enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
... your code
} ];
我喜欢做的不是使用“id obj”,而是使用实际类型(以避免在块中强制转换):
[myCollection enumerateObjectsUsingBlock:^(NSDictionary *dict, NSUInteger idx, BOOL *stop)
{
... your code
} ];
当我这样做时,编译器和分析器(4.4)都不会抱怨。
如果您需要在此方法之外设置变量,则必须将其设为块变量:
__block int foo = 0;
[myCollection enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop)
{
foo = MAX(foo, [num integerValue]);
} ];
编辑:作为澄清,您的问题的直接答案是“否”,语句“self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array”被评估一次,最终对象存储为堆栈上的临时对象。此外,您可以对块枚举使用相同的技术 - 语句被评估一次,最终返回的对象用于枚举。
__block int foo = 0;
[self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop)
{
foo = MAX(foo, [num integerValue]);
} ];
EDIT2:我在 SO 上找到了另一个讨论相同主题的线程。关于块枚举,我错过的一点是,您可以使用稍微复杂的方法指定它们应该同时(或反向)运行:
enumerateObjectsWithOptions:usingBlock:
随着 iOS 设备获得越来越多的核心,这可能是一个巨大的胜利,这取决于你在做什么。
@bbum 对这个问题的回答(以及其他问题)在这里。