Objective c Cocoa NSArray/NSSet:-makeObjectsPerformSelector:vs.快速枚举

Objective c Cocoa NSArray/NSSet:-makeObjectsPerformSelector:vs.快速枚举,objective-c,cocoa,macos,Objective C,Cocoa,Macos,我想对存储在NSSet中的多个对象执行相同的操作 我的第一次尝试是使用快速枚举: for (id item in mySetOfObjects) [item action]; 这很好用。然后我想到: [mySetOfObjects makeObjectsPerformSelector:@selector(action)]; 现在,我不知道什么是最好的选择。据我所知,这两种解决方案是等价的。但是,是否有理由认为一种解决方案优于另一种解决方案?我主张使用makeObjectsPerfor

我想对存储在
NSSet
中的多个对象执行相同的操作

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

for (id item in mySetOfObjects)
    [item action];
这很好用。然后我想到:

[mySetOfObjects makeObjectsPerformSelector:@selector(action)];

现在,我不知道什么是最好的选择。据我所知,这两种解决方案是等价的。但是,是否有理由认为一种解决方案优于另一种解决方案?

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

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

在苹果的文档中,标题为“展开循环”的部分简要提到了这个主题


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

makeObjectsPerformSelector:可能会稍微快一点,但我怀疑99%的时间里是否会有实际的差异。不过,它更简洁易读,我会使用它,因为这个原因。

我不会使用makeObjectsPerformSelector,原因很简单,它是一种您很少看到的调用。举例来说,这就是为什么我需要在数组枚举时添加调试代码,而使用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];
}

--汤姆

我也被问到了这个问题。我在苹果文档“集合编程主题”的“”下找到以下内容:

NSSet方法objectEnumerator允许 您将遍历集合1的元素 一个接一个。及 选择器的MakeObjectsPerformSelector:和 makeObjectsPerformSelector:withObject: 方法提供发送消息的方法 到集合中的单个对象。在里面 大多数情况下,应该使用快速枚举 之所以使用它,是因为它更快、更多 比使用N分子或 makeObjectsPerformSelector: 方法。有关枚举的详细信息,请参见 枚举:遍历 收藏的元素。”


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

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

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

唯一一次不是这样的是当内存开始填满时(当我开始用数百万个对象运行它时),之后它开始丢失到“makeObjectsPerformSelector”


很抱歉,我没有拍摄代码的快照,但这是一个非常简单的测试,我强烈建议您亲自尝试一下。

谢谢您的链接,我不知道此文档!正如您所说,“展开循环”部分“显然,Cocoa开发人员已经使用-makeObjectsPerformSelector进行了内部优化:我的荣幸。里面有一些有趣的东西。