可変長引数とブロック構文

同一のコントローラーでUIAlertViewを複数使う事があった。
わざわざコントローラー以外をデリゲートにするのも面倒なので
UIAlertViewのサブクラスを作りブロック部分でコールバックを受ける事にした。

参考:Objective-Cで可変引数
http://tea-leaves.co.jp/home/ja/article/1365947182

//ヘッダでUIAlertViewDelegateを設定
//ブロック部分の型を定義
typedef void (^AlertViewCompletion)(UIAlertView *alertView, NSInteger buttonIndex);

実装は下記のように・・・

@implementation AlertViewWithBlock{
    AlertViewCompletion _block;
}

- (id)initWithFrame:(CGRect)frame
{
    self = [super initWithFrame:frame];
    if (self) {
        self.delegate = self;
    }
    return self;
}

- (id)initWithTitle:(NSString *)title message:(NSString *)message completion:(AlertViewCompletion)completion cancelButtonTitle:(NSString *)cancelButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ...{

    self = [super init];

    if(self){

        [self setTitle:title];
        [self setMessage:message];
        [self setDelegate:self];

        va_list args;
        va_start(args, otherButtonTitles);

        for (NSString *anOtherButtonTitle = otherButtonTitles; anOtherButtonTitle != nil; anOtherButtonTitle = va_arg(args, NSString*)) {
            //UIAlertViewは可変長引数をそのまま渡せないので
            //addButtonWithTitleで可変長引数でわたってきた分ボタンを追加
            [self addButtonWithTitle:anOtherButtonTitle];
        }
        va_end(args);

        if(cancelButtonTitle){
            [self addButtonWithTitle:cancelButtonTitle];
        }

        _block = completion;
    }
    return self;
}

- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
    _block(alertView,buttonIndex);
}

こんな感じでしょうか。
ARC環境での実装です。
ブロック内の循環参照等を検証する必要がありますが、一旦ここまでにしておきます。

iOS

コメントを残す

メールアドレスが公開されることはありません。 * が付いている欄は必須項目です