Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/24.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Objective c 这是使用快速枚举的低效方法吗?_Objective C_Ios_Fast Enumeration - Fatal编程技术网

Objective c 这是使用快速枚举的低效方法吗?

Objective c 这是使用快速枚举的低效方法吗?,objective-c,ios,fast-enumeration,Objective C,Ios,Fast Enumeration,我不完全了解枚举的工作原理,但比较以下两种情况: for(NSObject *object in self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array) { // do something } vs 在第一个例子中,它会在每次迭代中遍历整个链来获得数组吗?我应该使用第二种方法吗?这可能是特定于编译器的(即未定义)。如果您感到困扰,请添加一些计时代码,了解您自己: #import <sys/

我不完全了解枚举的工作原理,但比较以下两种情况:

for(NSObject *object in self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array) {
    // do something
}
vs


在第一个例子中,它会在每次迭代中遍历整个链来获得数组吗?我应该使用第二种方法吗?

这可能是特定于编译器的(即未定义)。如果您感到困扰,请添加一些计时代码,了解您自己:

#import <sys/time.h>

static unsigned getTickCount()
{
    struct timeval tv;
    gettimeofday(&tv, 0);
    return (unsigned)((tv.tv_sec * 1000) + (tv.tv_usec / 1000));
}

然而,你必须拥有一个相当大的数组,才能注册任何高于
0

的内容。当苹果公司推出快速枚举时,我在WWDC工作,当时(我记得)我们被告知右手对象被移到了临时对象中。此外,由于这项工作:

for(在[myCollection ReverseObject枚举器]中的id foo)

您可以看到,执行快速枚举的集合采用“快速枚举协议”(NSFastEnumeration),该协议有一种方法:

– countByEnumeratingWithState:objects:count:
该方法返回一个对象的C数组,该数组允许非常快速地进行枚举,再次支持一次性使用右侧


话虽如此,苹果目前建议开发者(WWDC)使用块枚举,他们声称块枚举速度更快,生成的代码更少:

[myCollection enumerateObjectsUsingBlock:^(id obj, NSUInteger idx, BOOL *stop)
{
... your code
} ];
我喜欢做的不是使用“id obj”,而是使用实际的类型(以避免在块中强制转换):

当我这样做时,编译器和分析器(4.4)都不会抱怨

如果需要在此方法之外设置变量,则必须将其设置为块变量:

__block int foo = 0;
[myCollection enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop)
{
   foo = MAX(foo, [num integerValue]);
} ];
编辑:作为澄清,您的问题的直接答案是“否”,语句“self.myParent.parents.granfathersMother.counce.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:我在上面找到了另一个讨论同样话题的帖子。关于块枚举,我遗漏的一点是,您可以使用稍微复杂一点的方法指定它们应该并发运行(或反向运行):

enumerateObjectsWithOptions:usingBlock:
随着iOS设备越来越核心化,这可能是一个巨大的胜利,这取决于你在做什么


@bbum对这个问题(以及其他问题)的回答是。

myParent
getter中设置一个断点并检查整个循环是否只命中一次会更容易(也更可靠)…@omz是的,这很好,但不会告诉你它是否重要。最后一点也是为什么每次迭代都访问getter链并不重要的原因。在第一次访问之后,方法的缓存机制开始发挥作用,如果您没有真正庞大的数据集,那么使用什么并不重要。@JustSid您如何知道这些getter的确切功能?也许他们需要进行某种昂贵的计算才能得到结果。那么,无论他们被打了1000次电话,还是仅仅打了一次电话,这都很重要。(此外,方法调用从来都不是“免费的”)@omz非常有道理,对不起,我的措辞有点愚蠢。我的意思是,这很可能无关紧要,而且这个问题闻起来很像是过早优化。该方法返回一个C对象数组,让枚举非常快速,再次支持一次性使用右侧+1--对。如果“快速”是目的,这将是正确的方法。集合是枚举的,而不是任意表达式。如果在这个构造中需要速度或正确性,表达式返回的变量甚至不能作为考虑因素。David,我不记得有人说过这句话。哪个世界野生动物保护协会的演讲会这么说?另外,我刚刚运行了一个快速实验,对于几种不同的情况,我永远看不到调用EnumerateObjectsSusingBlock比数组上的快速枚举更快。在调试构建中,快速枚举要快两个数量级。但调试毫无意义。在发布版本上,它们非常接近,但块枚举从来没有更快过。@JodyHagins等等,调试版本和发布版本有什么区别?我认为这只是一个证书和资源调配等问题?您可以通过更改方案中的设置来确定差异,但通常调试版本没有优化,而发布版本支持大多数优化。您可以通过选择Scheme轻松切换,然后运行,并在调试/发布之间切换。@JodyHagins您真的看过所有WWDC视频吗?;)
__block int foo = 0;
[myCollection enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop)
{
   foo = MAX(foo, [num integerValue]);
} ];
__block int foo = 0;
[self.myParent.parentsParents.granfathersMother.cousin.unclesNephew.array enumerateObjectsUsingBlock:^(NSNumber *num, NSUInteger idx, BOOL *stop)
{
   foo = MAX(foo, [num integerValue]);
} ];
enumerateObjectsWithOptions:usingBlock: