UIAlertViewのボタンイベントをDelegateじゃなくてBlocksで処理したい
UIAlertViewでアラートを表示するのは簡単ですが、ボタンが押された時のイベントを受け取るのに毎回Delegateを定義するのはめんどくさいですよね。
仕方がないので、Blockを引数にできるクラスをUIAlertViewから派生させて作ってみました。
まずはインターフェース。 UIAlertViewのinitWithTitleをベースに、cancelイベント(キャンセルボタンではなく、モードレスでHomeが押された時に発生すると読んだような記憶がありますが、正確には憶えていません)と、ボタン押し下げイベントのハンドラをBlockで渡すようにしてます。ついでに、cancelButtonTitleは無しにして、全部buttonTitlesで定義するようします。並び順は自分で管理しますよってことで。
@interface AlertViewWithBlock : UIAlertView <UIAlertViewDelegate>
- (id)initWithTitle:(NSString *)title message:(NSString *)message cancelHandler:(void (^)(UIAlertView* view))cancelHandler buttonHandler:(void (^)(UIAlertView* view, NSInteger index))buttonHandler buttonTitles:(NSString *)buttonTitles, ... NS_REQUIRES_NIL_TERMINATION;
@end
実装側はこんな感じ。Objective-Cでも可変引数はCと同じで良いみたい。Blockの型とか変数宣言とか、ちゃんと理解できるまでかなり混乱しました。
@implementation AlertViewWithBlock
{
void (^varbuttonHandler)(UIAlertView*, NSInteger);
void (^varcancelHandler)(UIAlertView*);
}
- (id)initWithTitle:(NSString *)title message:(NSString *)message cancelHandler:(void (^)(UIAlertView*))cancelHandler buttonHandler:(void (^)(UIAlertView*, NSInteger))buttonHandler buttonTitles:(NSString *)buttonTitles, ...
{
self = [self initWithTitle:title message:message delegate:self cancelButtonTitle:nil otherButtonTitles:nil];
if(self){
va_list argumentList;
if(buttonTitles){
[self addButtonWithTitle:buttonTitles];
va_start(argumentList, buttonTitles);
id eachObj;
while ((eachObj = va_arg(argumentList, id))){
[self addButtonWithTitle: eachObj];
}
va_end(argumentList);
}
varcancelHandler = cancelHandler;
varbuttonHandler = buttonHandler;
}
return self;
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex{
if(varbuttonHandler){
varbuttonHandler(alertView,buttonIndex);
}
}
- (void)alertViewCancel:(UIAlertView *)alertView{
if(varcancelHandler){
varcancelHandler(alertView);
}
}
@end
そして使い方はこんな感じ
AlertViewWithBlock* alert = [[AlertViewWithBlock alloc] initWithTitle:@"タイトル" message:@"メッセージ" cancelHandler:^(UIAlertView* alertView){
NSLog(@"Cancel");
} buttonHandler:^(UIAlertView* alertView, NSInteger buttonIndex){
NSLog(@"Pushed %d Button",buttonIndex);
} buttonTitles:@"キャンセル",@"OK", nil];
[alert show];
3時間くらい時間かけちゃいましたが、これで便利になるのかどうかは微妙な感じです。