2009-02-24 5 views
13

NSSetに格納されている複数のオブジェクトに対して同じアクションを実行します。Cocoa NSArray/NSSet:-makeObjectsPerformSelector:高速列挙型と比較して

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

かなり正常に動作します:

私の最初の試みは、高速列挙を使用していました。次に、私は考えました:

[mySetOfObjects makeObjectsPerformSelector:@selector(action)]; 

そして今、私は最良の選択肢がわかりません。私が理解する限り、2つのソリューションは同等です。しかし、あるソリューションを他のソリューションよりも優先させるという議論はありますか?

答えて

21

私はmakeObjectsPerformSelectorを使用すると主張します。これはNSSetオブジェクトが独自のインデックス作成、ループ、メッセージディスパッチを処理できるようにするためです。 NSSetコードを書いた人は、その特定のループを実装する最良の方法を知っている可能性が最も高いです。

最悪の場合、それらはまったく同じループを実装するだけで、わずかにクリーンなコード(ループを囲む必要はありません)が得られます。せいぜい、彼らは内部最適化をいくつか行い、コードは実際より速く実行されます。

トピックは、AppleのCode Speed Performance文書の「Unrolling Loops」セクションで簡単に説明しています。

パフォーマンスが懸念される場合は、セット内のオブジェクトに対してセレクタを実行するクイックプログラムを設定するのが最適です。それは数百万回実行し、時間の違いは、2つの異なるケースの違い。

+0

リンクをありがとう、私はこの文書を知らなかった! Cocoa開発者が-makeObjectsPerformSelector: – mouviciel

+0

を使って内部最適化を行ったことを明確に述べています。そこには興味深いものがあります。 –

2

makeObjectsPerformSelector:は少し速いかもしれませんが、実用的な差は99%あるとは思えません。それはもう少し簡潔で可読ですが、私はその理由でそれを使用します。

4

単純な理由からmakeObjectsPerformSelectorは使用しません。なぜなら、それほど頻繁に表示されない呼び出しの種類だからです。ここでは例を挙げます - 配列が列挙されるときにデバッグコードを追加する必要があります。実際のno noであるリリースモードでのコードの動作を変更しない限り、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]; 
} 

--Tom

7

私もこの質問を提示されました。

あなたは1で設定された1 の要素をトラバースすることができます objectEnumerator NSSet方法:私は「Sets: Unordered Collections of Objects」は、次の下のAppleのドキュメント「トピックプログラミングコレクション」で見つけます。 themakeObjectsPerformSelector:および makeObjectsPerformSelector:withObject: メソッドは、セット内の個々のオブジェクトにメッセージ を送信するためのメソッドを提供します。 のほとんどの場合、NFCnumeratorまたは のmakeObjectsPerformSelector: メソッドを使用するよりも速く、より高速であるため が高速で、 がフレキシブルである必要があります。列挙の詳細については、 "列挙: コレクションの要素をトラバースするを参照してください。"

これにより、Fast Enumerationは依然としてこのアプリケーションにとって最も効率的な手段であると私は信じています。

1

(iOS 5.0〜6.0のように)NSCollectionオブジェクトのいずれかを反復する最も速い方法は、スピードが唯一の問題(つまり、小さなCPUサイクルがカウントされるレンダリングエンジンをいくつか作成している場合)です。さまざまな "enumerateObjectsUsingBlock"メソッド私はこれがなぜであるか分かりませんが、テストしましたが、これはそのように思われます...

私は小さなテストを書いて、数十万のオブジェクトのコレクションを作成しました。 。これらのコレクションのそれぞれは、さまざまなタイプの繰り返し(forループ、高速列挙、makeObjectsPerformSelector、およびenumerateObjectsUsingBlock)を何百回も実行するよう強制されました。ほとんどの場合、 "enumerateObjectsUsingBlock"メソッドがテストの間に手軽に勝ちました。メモリがいっぱいにし始めたとき、それは「makeObjectsPerformSelector」に失い始めた後に、(私は何百万人ものオブジェクトのでそれを実行し始めたとき)

これが本当ではなかった唯一の時間でした。

私はコードのスナップショットを取っていませんでしたが、実行するには非常に簡単なテストです。私はそれを試してみることを強くお勧めします。 :)

関連する問題