[解決済み】NSArrayを反復処理する方法は?
質問
NSArrayを繰り返し処理するための標準的なイディオムを探しています。私のコードはOS X 10.4+に適したものである必要があります。
どのように解決するのですか?
10.5+/iOSで一般的に推奨されるコードです。
for (id object in array) {
// do something with object
}
に準拠したコレクション内のオブジェクトを列挙するために使用されます。
NSFastEnumeration
プロトコルに準拠しています。この方法は、(1回のメソッド呼び出しで得られる)複数のオブジェクトへのポインタをバッファに格納し、ポインタ演算でバッファを進めることで反復処理するため、速度面で有利です。これは
大いに
を呼び出すよりも高速です。
-objectAtIndex:
をループさせる。
また、技術的には
できる
をステップ実行するためにフォーインループを使用します。
NSEnumerator
しかし、これでは高速な列挙の利点がほとんどなくなってしまうことがわかりました。その理由は、デフォルトの
NSEnumerator
の実装は
-countByEnumeratingWithState:objects:count:
は、各コールでバッファにオブジェクトを1つだけ配置します。
で報告しました。
radar://6296108
(Fast enumeration of NSEnumerators is sluggish) が、Not To Be Fixed として返されました。その理由は、高速列挙はオブジェクトのグループを事前にフェッチするため、列挙子内の所定のポイントまでしか列挙せず(例えば、特定のオブジェクトが見つかるか、条件を満たすまで)、ループから抜け出した後に同じ列挙子を使用する場合、いくつかのオブジェクトがスキップされることがよくあるためです。
OS X 10.6 / iOS 4.0 以上でコーディングする場合、配列やその他のコレクションを列挙するためにブロックベースのAPIを使用するオプションも用意されています。
[array enumerateObjectsUsingBlock:^(id object, NSUInteger idx, BOOL *stop) {
// do something with object
}];
を使用することもできます。
-enumerateObjectsWithOptions:usingBlock:
を渡すと
NSEnumerationConcurrent
および/または
NSEnumerationReverse
をオプションの引数として指定します。
10.4以前
10.5以前の標準的なイディオムとしては
NSEnumerator
というように、whileループを使用します。
NSEnumerator *e = [array objectEnumerator];
id object;
while (object = [e nextObject]) {
// do something with object
}
シンプルにすることをお勧めします。配列の型に縛られるのは柔軟性に欠け、また
-objectAtIndex:
は、10.5+での高速列挙による改善に比べたら、どうせ取るに足らないものです。(高速列挙は実際には基礎となるデータ構造のポインタ演算を使用し、メソッド呼び出しのオーバーヘッドのほとんどを取り除きます)。早まった最適化は決して良い考えとは言えません。とにかくボトルネックではない問題を解決するために、より複雑なコードになってしまうからです。
を使用する場合
-objectEnumerator
のような)他の列挙可能なコレクションに簡単に変更することができます。
NSSet
のキーは
NSDictionary
など)に切り替えたり、あるいは
-reverseObjectEnumerator
を使えば、配列を逆に列挙することができ、他のコードを変更することなく、すべてを行うことができます。もし反復処理のコードがメソッド内にあるならば、任意の
NSEnumerator
を気にする必要はありません。
何
を反復している。さらに
NSEnumerator
(少なくとも Apple のコードで提供されるものは) 列挙しているコレクションを、さらにオブジェクトがある限り保持するので、自動解放されたオブジェクトがいつまで存在するか心配する必要はありません。
おそらく
NSEnumerator
(または高速列挙)があなたを守るのは、変更可能なコレクション(配列またはその他)があなたの下で変更されることです。
知らないうちに
列挙している間に インデックスでオブジェクトにアクセスすると、奇妙な例外や1つ違いのエラーに遭遇することがあり、(多くの場合、問題が発生してからずっと後に)デバッグするのが恐ろしいことになります。標準的なイディオムの1つを使った列挙は、"fail-fast"の動作をするので、(間違ったコードが原因の)問題は、変異が起こった後に次のオブジェクトにアクセスしようとすると、すぐに現れます。プログラムがより複雑になり、マルチスレッドになったり、サードパーティのコードが変更する可能性があるものに依存するようになると、脆弱な列挙コードはますます問題になります。カプセル化と抽象化 FTW! :-)
関連
-
[解決済み] enumを列挙するには
-
[解決済み] Java Mapの各エントリを効率的に反復処理するには?
-
[解決済み] キーボードがあるときに、UITextFieldを編集開始時に上に移動させるには?
-
[解決済み] iOSまたはmacOSで、インターネット接続が有効かどうかを確認するにはどうすればよいですか?
-
[解決済み] 反復処理中にリストから項目を削除するには?
-
[解決済み] Swiftでindexとelementでループを反復させる方法
-
[解決済み] Javaでリストを反復処理する方法
-
[解決済み] objectForKeyとvalueForKeyの違い?
-
[解決済み】PHPの'foreach'は実際どのように動作するのですか?
-
[解決済み】Objective-Cでクラスレベルのプロパティを宣言するにはどうすればいいですか?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] イニシャライザーの要素がコンパイル時定数でない
-
[解決済み] クラス 'test_coredataAppDelegate' の重複したインターフェイス宣言
-
[解決済み] objcの "pi "と "M_PI "の違いは何ですか?
-
[解決済み] C言語で純粋にiOSアプリを書く方法
-
[解決済み] objectForKeyとvalueForKeyの違い?
-
[解決済み] NSTimerの使い方を教えてください。
-
[解決済み】iOS7でステータスバーを隠すことができない。
-
[解決済み】UITableViewからセパレータラインを削除する方法はありますか?
-
[解決済み】なぜObjective-Cのファイルには.mという拡張子がついているのですか?
-
[解決済み】ストーリーボードで、複数のコントローラで使用するためのカスタムセルを作成する方法は?