ブロックオブジェクト
ブロックオブジェクトは、引数、必要に応じて格納され、複数のスレッドで使用できる関数表現を構成できるようにする C レベルの統語と実行時の機能です。関数表現は、参照でき、ローカル変数へのアクセスを保護できます。他の言語や環境では、ブロックオブジェクトは、時々クロージャまたはラムダ関数と呼ばれています。それらが値を持っているかのように渡されることができる作業単位を作成(つまり、コードセグメントである) したいときに、ブロックを使用します。ブロックは、より柔軟な、より強力なプログラミング能力を提供します。例えば、コールバックを記述したり、コレクションのすべての項目で操作を実行するために、それらを使えます。
ブロックの宣言
多くの状況では、インラインブロックを使用し、それらを宣言する必要はありません。しかしながら、アスタリスクポインタ(*)の代わりにキャレット(^)を使用する点を除いて、宣言構文は、関数ポインタの標準構文と似ています。たとえば、次の例文では、3つのパラメータが必要な、float 値を返すブロックを参照する変数 aBlock を宣言します。
float (^aBlock)(const int*, int, float);
ブロックの作成
ブロック式の始めを示すためにキャレット(^)演算子を使用し、終わりを示す為にセミコロン(;)を使います。次の例は、単純なブロックを宣言し、以前に宣言したブロック変数(oneFrom)に割り当てます。
int (^oneFrom)(int); oneFrom = ^(int anInt) { return anInt - 1; };
最後の閉じるセミコロンは、標準の C の行末マーカーとして必要とされます。
明示的にブロック表現の戻り値を宣言しない場合、自動的にブロックの内容から推測することができます。
変更可能なブロックの変数
__のブロックストレージ修飾子を使用することで、ローカルに変数を宣言し、このような変数は、ブロック内の参照によって提供され、そのように変更可能であることを示すために囲んで構文スコープに宣言されています。すべての変更は、同じ外側の構文スコープ内で定義され、他のブロックを含め、囲む構文スコープに反映されています。
ブロックを使用する
変数としてブロックを宣言した場合、機能(関数)として機能するように使用することができます。以下の例では、出力として 9 を印刷します。
printf("%d\n", oneFrom(10));
しかし、典型的には、関数の引数やメソッドなどのブロックを渡します。これらのケースでは、多くの場合、ブロックをインラインで作成して下さい。
以下の例は、NSSet のオブジェクトがローカル変数で指定された word を含んでいるかどうかを判断し、別のローカル変数(found) に値を設定し YES に設定し、(検索を停止します) もしそうなら。以下の例では、found は、__block 変数として宣言されています。
__block BOOL found = NO; NSSet *aSet = [NSSet setWithObjects: @"Alpha", @"Beta", @"Gamma", @"X", nil]; NSString *string = @"gamma"; [aSet enumerateObjectsUsingBlock:^(id obj, BOOL *stop) { if ([obj localizedCaseInsensitiveCompare:string] == NSOrderedSame) { *stop = YES; found = YES; } }]; // At this point, found == YES
この例では、ブロックは、メソッドの引数リスト内に含まれています。ブロックも、スタック・ローカル変数を使用して作られています。
比較演算
Cocoa 環境内のブロックで実行される、より一般的な操作の1つは、2つのオブジェクト間の、たとえば、配列の内容を並べ替えて比較する事です。Objective-C の実行環境がブロックタイプを定義し - NSComparator - これらの比較のために使用します。
前提条件の記事
関連記事
既出の議論
ブロックでの作業
次の章
前の章