Blocksが使えるようになってはや数年。未だに書式が覚えられないわたし(あなた)の為に書き方をまとめてみた。
基本
基本型
戻り値 (^名前) (引数)
(私が勝手に決めた)基本型はこれ。これを覚えないことには始まらない。とにかくこれだけは覚える。
戻り値と引数は一般的なCの関数の書き方と同じなので、名前の書き方だけ (^名前) になったと覚えるのがいい。
(例)BOOL (^completion)(BOOL canceled) = ...;
この基本型を元に各場面でどう使うかを見ていく。
変数宣言・typedef宣言
変数宣言なら
戻り値 (^名前) (引数) = …;
typedef宣言なら
typedef 戻り値 (^名前) (引数);
両方とも基本型がそのまま使える。
(例)typedef BOOL (^LKCompletion)(BOOL canceled);
プロパティ宣言
プロパティ宣言で使う時にも基本型がそのまま使える。
@property (copy) 戻り値 (^名前) (引数)
Blocksをプロパティ宣言する場合は copy にしておくのがポイント。
(例)@property (copy) BOOL (^completion)(BOOL canceled);
メソッド引数
メソッド引数にした時に書き方が若干変わる。形が変わるのが Blocks構文を覚えにくくさせている理由の一つ。
(例)- (void)loadImageCompletion:(BOOL(^)(BOOL canceled))completion;
ただ落ち着いて見るとObjective-C標準のメソッド引数の書式に従って基本型を変形しているだけなので実は難しくない。
もともとメソッド引数は「(型)名前」というスタイルなので基本型をそれに合わせて変形ればいい。
戻り値 (^名前) (引数) ※基本型
↓
↓ 名前を後ろへ切り出す ←メソッド引数名は最後にくるから
↓
戻り値 (^) (引数)名前
↓
↓ 引数の型となる範囲を( )で囲う ←メソッド標準の書き方
↓
(戻り値 (^) (引数)) 名前
基本型をメソッド引数の書き方に合わせたものだと覚えておくといい。
Blocks定義
^戻り値 (引数) {...}
やはりBlocks構文を覚えくくさせている原因の一つ。基本型と書き方が異なる。
(例)BOOL (^display)(BOOL animated) = ^BOOL(BOOL animated) {return YES;};
こちらはメソッド引数の時と異なり変形ルールが想定できない。仕方がないので基本型同様に暗記する。なおメソッド引数にBlocks定義を記述する場合、Xcodeならコーディング時にBlocksの書式を補完してくれる。この為記憶を頼りに記述するケースは実際には多くないかもしれない。
(例)[hoge loadImageCompletion:^BOOL(BOOL canceled) {
:
}];
まとめ
こうして見ていくとBlocksの書き方が覚えにくいのには理由があって、書き方のパターンが何種類もあるのが原因だとわかる。逆にそれらが整理できて把握できれば自分で書けるようになる。
最低限覚えるべきは次の2つ。
基本型
戻り値 (^名前) (引数)
Blocks定義
^戻り値(引数) {...}
それ以外は基本型がそのまま使えるのと、メソッド引数の場合は基本型の応用なので変形ルールを知っておけば書式を無理に覚える必要は無い。またBlocks定義を書く時は、多くの場合 Xcodeが補完してくれるので覚えておく必要性は基本型に比べると実は少ない(人によるが)。なので、乱暴に言えば基本型だけ覚えればどうにかなる。
なお「基本型」など、この記事の分類は私が勝手に決めたものなのでご注意を(公式の呼び名ではない)。
応用
voidな引数と戻り値は省略できるケースがある。
引数省略
引数が voidの場合は省略できる。
BOOL (^execute)(void) = …;
↓
BOOL (^execute)( ) = …;
- (void)displayScreen:(void(^)(void))didAppear;
↓
- (void)displayScreen:(void (^)( ))didAppear;
戻り値省略
Blocks定義の時は戻り値が voidであれば省略できる。
(例)^void (void) { … }
↓
^(void) { … }
Blocks定義の場合、引数が voidならさらに引数のカッコ ()自体も省略できる。
(例)^{ … }
よく見かける ^{...} は実は ^void(void){...} が省略されたもの。
Blocks定義以外で戻り値voidは省略できないので注意。
○ @property (copy) void (^didAppear)(BOOL animated);
☓ @property (copy) (^didAppear)(BOOL animated);
参考・お役立ち情報
Block Cheat Sheet
Block Declaration Syntax List
Recursive Blocks(再帰ブロック)の書き方の紹介あり。
坂本氏担当の第5章にBlocksの説明あり。GCDと合わせてわかりやすい。
こちらも坂本氏の本。詳細な解説だがそれでいてわかりやすい。ARCの詳説もあるのでかなりおすすめ。私は紙で入手したが電子書籍版もあると思う。
- - - -
ツッコミあればお願いします。間違い等は訂正します。