37
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 5 years have passed since last update.

Block引数の安全な呼び出し方

Last updated at Posted at 2014-01-27

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
37
38
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
38

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?