我并不完全理解枚举速度有多快的细节,但比较以下两种情况:
for(NSObject *object in self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array) {
// do something
}
VS。
NSArray *array = self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array;
for(NSObject *object in array) {
// do something
}
在第一个例子中,它会在每次迭代时通过整个链来获取数组吗?我应该使用第二种方式吗?
答案 0 :(得分:7)
当Apple推出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'被评估一次,最后的对象存储为temp堆栈。此外,您可以使用与块枚举相同的技术 - 语句被评估一次,最后返回的对象用于枚举。
__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对问题(以及其他人)的回答是here。
答案 1 :(得分:3)
这可能是编译器特定的(即未定义)。如果你感到困扰,那么添加一些计时代码并找出自己:
#import <sys/time.h>
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
以上的任何内容,您必须拥有一个非常大的数组。