Cocoa NSArray / NSSet:-makeObjectsPerformSelector:与快速枚举

时间:2009-02-24 16:50:07

标签: objective-c cocoa macos

我想对存储在NSSet

中的多个对象执行相同的操作

我的第一次尝试是使用快速枚举:

for (id item in mySetOfObjects)
    [item action];

工作得很好。然后我想到了:

[mySetOfObjects makeObjectsPerformSelector:@selector(action)];

现在,我不知道什么是最好的选择。据我了解,这两种解决方案是等效的。但是,是否有理由选择一种解决方案而不是另一种?

5 个答案:

答案 0 :(得分:22)

我认为使用makeObjectsPerformSelector,因为它允许NSSet对象处理自己的索引,循环和消息调度。编写NSSet代码的人最有可能知道实现该特定循环的最佳方式。

在最坏的情况下,他们只是实现完全相同的循环,你获得的只是稍微清晰的代码(不需要封闭循环)。充其量,他们进行了一些内部优化,代码实际上运行得更快。

Apple的Code Speed Performance文档中标题为“展开循环”的部分简要介绍了该主题。

如果您关心性能,最好的办法是设置一个快速程序,在一组中的对象上执行一些选择器。让它运行数百万次,并计算两种不同情况之间的差异。

答案 1 :(得分:7)

我也被问到了这个问题。我在“Sets: Unordered Collections of Objects”下的Apple文档“Collections Programming Topics”中找到了以下内容:

  

NSSet方法objectEnumerator允许   你遍历集合的元素   一个人。和   themakeObjectsPerformSelector:和   makeObjectsPerformSelector:withObject:   方法提供发送消息   到集合中的单个对象。在   大多数情况下,快速枚举应该是   使用是因为它更快更多   灵活性比使用NSEnumerator或   makeObjectsPerformSelector:   方法。有关枚举的更多信息,请参阅   “枚举:遍历一个   集合的元素。“

这让我相信快速枚举仍然是此应用程序最有效的方法。

答案 2 :(得分:4)

我不会使用makeObjectsPerformSelector,原因很简单,那就是那种经常看不到的调用。这就是为什么例如 - 我需要在枚举数组时添加调试代码,除非你改变代码在Release模式下工作的方式,否则你真的不能用makeObjectsPerformSelector来做这个。

for (id item in mySetOfObjects)
{
    #if MY_DEBUG_BUILD
    if ([item isAllMessedUp])
        NSLog(@"we found that wily bug that has been haunting us"); 
    #endif

    [item action];
}

- 汤姆

答案 3 :(得分:2)

makeObjectsPerformSelector:可能会稍快一点,但我怀疑99%的时间会有任何实际差异。它有点简洁和可读,但我会因此而使用它。

答案 4 :(得分:1)

如果纯速度是唯一的问题(即你创建了一个渲染引擎,其中每个微小的CPU周期都很重要),迭代通过任何NSCollection对象(从iOS 5.0~6.0开始)的最快方法是各种各样的“enumerateObjectsUsingBlock”方法。我不知道为什么会这样,但我测试了它,这似乎就是这样......

我写了一个小测试,创建了数十万个对象的集合,每个对象都有一个方法,它总结了一个简单的int数组。每个集合都被迫执行各种类型的迭代(for循环,快速枚举,makeObjectsPerformSelector和enumerateObjectsUsingBlock)数百万次,几乎在所有情况下,“enumerateObjectsUsingBlock”方法都在测试过程中轻松获胜。

唯一不合适的时候是内存开始填满(当我开始用百万对象运行它时),之后它开始输给“makeObjectsPerformSelector”。

对不起,我没有拍摄代码的快照,但这是一个非常简单的测试,我强烈建议你试一试,亲眼看看。 :)