这是使用快速枚举的低效方法吗?
我并不完全理解枚举的快速程度,但比较以下两种情况:
for(NSObject *object in self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array) { // do something }
与
NSArray *array = self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array; for(NSObject *object in array) { // do something }
在第一个例子中,它是否会在每次迭代时通过整个链来获取数组? 我应该使用第二种方式吗?
当我推出Fast Enumeration时,我在WWDC上,并且(我记得)当时我们被告知右手对象被移入临时状态。 此外,它必须是因为这工作:
for([myCollection reverseObjectEnumerator]中的id foo)
您可以看到执行快速枚举的集合采用“快速枚举协议”(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对这个问题的反应(以及其他人)也在这里 。
这可能是编译器特定的(即未定义)。 如果您感到困扰,那么添加一些计时代码并找出自己:
#import static unsigned getTickCount() { struct timeval tv; gettimeofday(&tv, 0); return (unsigned)((tv.tv_sec * 1000) + (tv.tv_usec / 1000)); }
…
unsigned startTime = getTickCount(); for(NSObject *object in self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array) { // do something } unsigned endTime = getTickCount(); NSLog(@"That took %umS", endTime - startTime);
但是,为了注册0
以上的任何数据,你必须有一个非常大的数组。