我想对存储在NSSet
。
我的第一次尝试是使用快速枚举:
for (id item in mySetOfObjects)
[item action];
工作得很好。然后我想到了:
[mySetOfObjects makeObjectsPerformSelector:@selector(action)];
现在,我不知道什么是最好的选择。据我了解,这两种解决方案是等效的。但是,是否有理由选择一种解决方案而不是另一种?
答案 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”。
对不起,我没有拍摄代码的快照,但这是一个非常简单的测试,我强烈建议你试一试,亲眼看看。 :)