あなたが物事をどのように説明したいのかわからない。これが私の試みです:
ブロックはコードの一部です。を使用してブロックを作成する^{}
と、そのコードを変数に格納できます。あなたの場合(そしてほとんどの場合)、他の値と同様に、メソッドに引数としてすぐに渡されます。この例のブロックは、コードが実行されるときに値を指定する必要がある 1 つの引数を宣言します。変数object_in
にはいくつかのオブジェクトが含まれ、コードのブロックでそれを操作できます。
[array each:^(id object_in) {
NSLog(@"object: %@", object_in);
}];
メソッド内で、コードは引数変数に格納されblock
、ケースで名前が付けられます。次に、コードを実行します。これを行うには、ブロック引数として実数値のリストに括弧を追加します。現在object_out
、いくつかの実際の値が含まれているため、 に渡されobject_in
ます。
- (NSArray *)each:(void (^)(id))block {
for (id object_out in self) {
block(object_out); // executes the code of block with given argument
}
return self;
}
NSLog
これで、配列内のすべてのオブジェクトでステートメントが実行されます。
関数ポインタと非常によく似ています。あなたがそれについて何か知っているなら、それはより簡単かもしれません.そうでない場合は、気にしないでください:)
したがって、引数によって値をブロックに渡すことができますが、値をブロックに取得する 2 番目の方法もあります。ローカル変数のキャプチャに関するものですが、例では使用されていません。あなたまたは他の誰かが私に説明してほしい場合は、お気軽にコメントしてください。
編集:ここでは、キャプチャされた変数について簡単に説明します。で囲まれたすべてのコード{}
はスコープなので、ブロックもスコープです。スコープはネストされており、その中で作成されたローカル変数は、制御フローがスコープを離れるまでのみ有効です。子スコープは、親スコープの変数を使用できます。
以下のコード例は、2 つの配列を反復処理します。1 つはfor-in
ループで、もう 1 つ-each:
は質問のメソッドです。引数として渡されるブロックは少し異なります。親スコープから 1 つの変数を使用します (実際には、祖父母スコープからのものです)。このブロックが違うのはなぜですか?メソッドは、異なる値-each:
を含むたびに複数回実行されます。string
つまり、ブロックの 3 つのインスタンスがそれぞれ独自のstring
値で作成されます。
NSArray *strings = @[ @"A", @"B", @"C" ];
NSArray *numbers = @[ @1, @2, @3 ];
NSString *string = nil; // doing this to be more obvious
for (string in strings) {
// string is simple local variable
[numbers each:^(id number) {
// number is argument
NSLog(@"argument: %@, captured: %@", number, string);
}];
}
出力:
argument: 1, captured: A
argument: 2, captured: A
argument: 3, captured: A
argument: 1, captured: B
argument: 2, captured: B
argument: 3, captured: B
argument: 1, captured: C
argument: 2, captured: C
argument: 3, captured: C
したがって、3 つのインスタンスすべてに共通のコードと、それぞれに異なる (異なる可能性がある) いくつかの変数があります。これでクラス/オブジェクトの関係を思い出すなら、あなたは正しいです。
引数はブロックの呼び出しごとに異なり (前のコード例に示されています)、キャプチャされた変数はインスタンスごとに異なります。^{
ブロック定義( )のある行が実行されるたびに、新しいインスタンスが作成されます。