4

これは私には非常に奇妙な相互作用のように思えますが、同時にそれは機能するだけでなく、プロセスで警告やエラーをスローしません。一般的なブロックと、なぜこのようなものが正しいか間違っているのかをよりよく理解するために探しています。

このようなことをしてはいけない理由はありますか?

NSArray *array = [NSArray arrayWithObjects:^{NSLog(@"Block 1");}, ^{NSLog(@"Block 2");}, ^{NSLog(@"Block 3");}, nil];

for (id block in array) {
    [block invoke];
}
4

3 に答える 3

4

ブロックをNSArraysに入れるのは問題ありません。それらはオブジェクトです。実際、それらはから継承しNSObjectます。

ただし、それらをコピーする必要があります。これらのブロックはスタック上に作成され、現在のメソッドの終わりを超えて存続するには、ヒープに移動する必要があります。ARCを使用している場合、これは簡単です。

NSArray *array = [NSArray arrayWithObjects:[^{NSLog(@"Block 1");} copy], ...

MRRでは、バランスを取る必要があるcopyため、2つの不快なオプションがあります。一時を使用するか、配列を作成した直後に列挙しreleaseてすべてのメンバーに送信します。

invoke一方、送信は完全にコーシャではありません。これはプライベートな方法だからです。ブロックを呼び出す唯一の完全にAPI準拠の方法は、関数呼び出し構文を使用することです。

typedef GenericBlock dispatch_block_t;
for( GenericBlock block in array ){
    block();
}
于 2012-07-26T19:46:45.193 に答える
1

もちろん、それで結構です。どうして大丈夫じゃないの?

JavaScriptのような言語では、この手法はイベントハンドラーを登録するときに一般的です。

object.clickHandlers.push(function() { doStuff() });
object.clickHandlers.push(function() { doMoreStuff() });

ObjCブロックは実際のオブジェクトであるため、同様の手法を使用できなかった理由はわかりません。

しかし、私にとってもっと興味深い質問は、このパターンがあなたの目標が何であれ、最良の選択であるかどうかです。あなたが本当に私たちに言っていないこと。

于 2012-07-26T19:46:55.737 に答える
1

Objective-Cのブロックは「第一級市民」オブジェクトです。パラメータとして渡す、配列やディクショナリに格納するなど、通常のオブジェクトに対して実行できることは何でも、オブジェクトをブロックするために実行することもできます。

たとえば、ブロックオブジェクトの配列は、コンパイル時に認識されない一連のアクションをエンコードするのに役立つ場合があります。文字列でキー設定されたブロックオブジェクトの辞書は、スクリプト言語の実装などに役立つ可能性があります。

コレクションから取得したブロックを呼び出す最良の方法は、コレクションを適切なタイプにキャストし、通常のブロック呼び出し構文を使用することです。

于 2012-07-26T19:47:11.770 に答える