4

我不完全了解枚举速度如何工作的细节,但比较以下两种情况:

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
 }

在第一个示例中,它是否会在每次迭代时遍历整个链来获取数组?我应该使用第二种方式吗?

4

2 回答 2

7

当 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 对这个问题的回答(以及其他问题)在这里

于 2012-09-05T13:16:06.333 回答
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

于 2012-09-05T12:40:04.810 回答