Objective Cのブロックは非常に強力ですが、nilのブロック呼び出しを行うとEXC_BAD_ACCESSで落ちるという厄介な問題があります。blockにnilを与えること自体が不正に見えるかもしれませんが、Objective Cは言語仕様的にnilを許容するケースが多いので、nilを与えても落ちないように設計するべきだと思います。
チェックの方法にはいくつかのアプローチがあるのでサンプルを書いてみました。詳細はコメントをご覧下さい。
@interface BTKBlockNilCheck : NSObject
- (void) runBlockSample1 : (void (^)(NSError *error))block;
- (void) runBlockSample2 : (void (^)(NSError *error))block;
- (void) runBlockSample3 : (void (^)(NSError *error))block;
- (void) runBlockSample4 : (void (^)(NSError *error))block;
@end
@implementation BTKBlockNilCheck
- (void) runBlockSample1 : (void (^)(NSError *error))block
{
// チェックなしで呼び出し。ダメ、絶対。
block(nil);
}
- (void) runBlockSample2 : (void (^)(NSError *error))block
{
// 呼び出し前にチェック。
// シンプルな関数だと見通しが良い
if(block){
block(nil);
}
}
- (void) runBlockSample3 : (void (^)(NSError *error))block
{
// nilの場合にはdummyで置換
// 何度でも安全に呼び出せるので、一番オススメ。
if(!block){
block = ^(NSError *error){};
}
block(nil);
}
- (void) runBlockSample4 : (void (^)(NSError *error))block
{
// 常に独自のblockで置換
// 安全なだけでなく、block実行前後に処理を入れることができる
// 便利だが、常にblockが生成されてしまう。
block = ^(NSError *error){
if(block){
block(error);
}
};
block(nil);
}
@end