UIAlertViewやUIActionSheetはdelegateで選択結果を取得して処理を分岐します。このdelegateでというのが結構面倒ですが、iOS4からはblocksが利用できるので、blocksを利用すればUIAlertViewをつくると同時にボタンに対応する動作も記述できて使いやすくなります。
ネット上にはblocksでの拡張情報がいくつかありますが、以下がネットの情報を元に私が作成したblocks版UIAlertViewとUIActionSheetです。
CTAlertView.h
#import <UIKit/UIKit.h> @class CTAlertView; typedef void (^CTAlertViewButtonCallback)(CTAlertView *alertView, NSInteger index); @interface CTAlertView : UIAlertView <UIAlertViewDelegate> { @private void (^willPresentCallback_)(CTAlertView *); void (^didPresentCallback_)(CTAlertView *); void (^willDismissCallback_)(CTAlertView *, NSInteger); void (^didDismissCallback_)(CTAlertView *, NSInteger); NSMutableArray *buttonCallbacks_; } - (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle; -(void)addButtonWithTitle:(NSString*)title callback:(CTAlertViewButtonCallback)callback; -(void)setCancelButtonCallback:(CTAlertViewButtonCallback)block; -(void)setWillPresentCallback:(void (^)(CTAlertView *alertView))block; -(void)setDidPresentCallback:(void (^)(CTAlertView *alertView))block; -(void)setWillDismissCallback:(void (^)(CTAlertView *alertView, NSInteger index))block; -(void)setDidDismissCallback:(void (^)(CTAlertView *alertView, NSInteger index))block; @end |
CTAlertView.h
#import "CTAlertView.h" @interface CTAlertView () @property (nonatomic, retain) NSMutableArray *buttonCallbacks; - (BOOL)hasCancelButton; @end @implementation CTAlertView @synthesize buttonCallbacks=buttonCallbacks_; - (id)initWithTitle:(NSString *)title message:(NSString *)message cancelButtonTitle:(NSString *)cancelButtonTitle { self = [super initWithTitle:title message:message delegate:nil cancelButtonTitle:cancelButtonTitle otherButtonTitles:nil]; if (self) { self.delegate = self; self.buttonCallbacks = [NSMutableArray array]; if ([self hasCancelButton]) { [self setCancelButtonCallback:^(CTAlertView *alertView, NSInteger index){}]; } } return self; } - (void)dealloc { [willPresentCallback_ release]; [didPresentCallback_ release]; [willDismissCallback_ release]; [didDismissCallback_ release]; self.buttonCallbacks = nil; [super dealloc]; } -(void)addButtonWithTitle:(NSString*)title callback:(CTAlertViewButtonCallback)callback { id obj = [NSNull null]; if (callback) obj = [[callback copy] autorelease]; [self addButtonWithTitle:title]; [self.buttonCallbacks addObject:obj]; } -(void)setCancelButtonCallback:(CTAlertViewButtonCallback)callback { if (![self hasCancelButton]) return; if ([self.buttonCallbacks count] > 0) { [self.buttonCallbacks removeObjectAtIndex:0]; } [self.buttonCallbacks insertObject:[[callback copy] autorelease] atIndex:0]; } -(void)setWillPresentCallback:(void (^)(CTAlertView *alertView))block { [willPresentCallback_ release]; willPresentCallback_ = [block retain]; } -(void)setDidPresentCallback:(void (^)(CTAlertView *alertView))block { [didPresentCallback_ release]; didPresentCallback_ = [block retain]; } -(void)setWillDismissCallback:(void (^)(CTAlertView *alertView, NSInteger index))block { [willDismissCallback_ release]; willDismissCallback_ = [block retain]; } -(void)setDidDismissCallback:(void (^)(CTAlertView *alertView, NSInteger index))block { [didDismissCallback_ release]; didDismissCallback_ = [block retain]; } - (BOOL)hasCancelButton { return (self.cancelButtonIndex == 0); } #pragma mark - #pragma mark UIAlertViewDelegate -(void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex { id callback = [self.buttonCallbacks objectAtIndex:buttonIndex]; if (![callback isMemberOfClass:[NSNull class]]) { ((CTAlertViewButtonCallback)callback)((CTAlertView *)alertView, buttonIndex); } } -(void)willPresentAlertView:(UIAlertView *)alertView { if(willPresentCallback_) willPresentCallback_((CTAlertView *)alertView); } -(void)didPresentAlertView:(UIAlertView *)alertView { if(didPresentCallback_) didPresentCallback_((CTAlertView *)alertView); } -(void)alertView:(UIAlertView *)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex { if(willDismissCallback_) willDismissCallback_((CTAlertView *)alertView, buttonIndex); } -(void)alertView:(UIAlertView *)alertView didDismissWithButtonIndex:(NSInteger)buttonIndex { if(didDismissCallback_) didDismissCallback_((CTAlertView *)alertView, buttonIndex); } @end |
CTActionSheet.h
#import <UIKit/UIKit.h> @class CTActionSheet; typedef void (^CTActionSheetButtonCallback)(CTActionSheet *actionSheet, NSInteger index); @interface CTActionSheet : UIActionSheet <UIActionSheetDelegate> { @private NSMutableArray *buttonCallbacks_; void (^willPresentCallback_)(CTActionSheet *); void (^didPresentCallback_)(CTActionSheet *); void (^willDismissCallback_)(CTActionSheet *, NSInteger); void (^didDismissCallback_)(CTActionSheet *, NSInteger); } - (id)initWithTitle:(NSString *)title; - (void)addCancelButtonWithTitle:(NSString *)title callback:(CTActionSheetButtonCallback)callback; - (void)addDestructiveButtonWithTitle:(NSString *)title callback:(CTActionSheetButtonCallback)callback; - (void)addButtonWithTitle:(NSString *)title callback:(CTActionSheetButtonCallback)callback; - (void)setWillPresentCallback:(void (^)(CTActionSheet *actionSheet))callback; - (void)setDidPresentCallback:(void (^)(CTActionSheet *actionSheet))callback; - (void)setWillDismissCallback:(void (^)(CTActionSheet *actionSheet, NSInteger index))callback; - (void)setDidDismissCallback:(void (^)(CTActionSheet *actionSheet, NSInteger index))callback; @end |
CTActionSheet.m
#import "CTActionSheet.h" @interface CTActionSheet () @property (nonatomic, retain) NSMutableArray *buttonCallbacks; @end @implementation CTActionSheet @synthesize buttonCallbacks=buttonCallbacks_; - (id)initWithTitle:(NSString *)title { self = [super initWithTitle:title delegate:nil cancelButtonTitle:nil destructiveButtonTitle:nil otherButtonTitles:nil]; if (self) { self.delegate = self; self.buttonCallbacks = [NSMutableArray array]; } return self; } - (void)dealloc { self.buttonCallbacks = nil; [willPresentCallback_ release]; [didPresentCallback_ release]; [willDismissCallback_ release]; [didDismissCallback_ release]; [super dealloc]; } - (void)addCancelButtonWithTitle:(NSString *)title callback:(CTActionSheetButtonCallback)callback { NSUInteger index = [self.buttonCallbacks count]; [self addButtonWithTitle:title callback:callback]; self.cancelButtonIndex = index; } - (void)addDestructiveButtonWithTitle:(NSString *)title callback:(CTActionSheetButtonCallback)callback { NSUInteger index = [self.buttonCallbacks count]; [self addButtonWithTitle:title callback:callback]; self.destructiveButtonIndex = index; } - (void)addButtonWithTitle:(NSString*)title callback:(CTActionSheetButtonCallback)callback { id obj = [NSNull null]; if (callback) obj = [[callback copy] autorelease]; [self addButtonWithTitle:title]; [self.buttonCallbacks addObject:obj]; } -(void)setWillPresentCallback:(void (^)(CTActionSheet *actionSheet))callback { [willPresentCallback_ release]; willPresentCallback_ = [callback retain]; } -(void)setDidPresentCallback:(void (^)(CTActionSheet *actionSheet))callback { [didPresentCallback_ release]; didPresentCallback_ = [callback retain]; } -(void)setWillDismissCallback:(void (^)(CTActionSheet *actionSheet, NSInteger index))callback { [willDismissCallback_ release]; willDismissCallback_ = [callback retain]; } -(void)setDidDismissCallback:(void (^)(CTActionSheet *actionSheet, NSInteger index))callback { [didDismissCallback_ release]; didDismissCallback_ = [callback retain]; } #pragma mark - #pragma mark UIActionSheetDelegate - (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex { id callback = [self.buttonCallbacks objectAtIndex:buttonIndex]; if (![callback isMemberOfClass:[NSNull class]]) { ((CTActionSheetButtonCallback)callback)((CTActionSheet *)actionSheet, buttonIndex); } } - (void)willPresentActionSheet:(UIActionSheet *)actionSheet { if (willPresentCallback_) willPresentCallback_((CTActionSheet *)actionSheet); } - (void)didPresentActionSheet:(UIActionSheet *)actionSheet { if (didPresentCallback_) didPresentCallback_((CTActionSheet *)actionSheet); } - (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex { if (willDismissCallback_) willDismissCallback_((CTActionSheet *)actionSheet, buttonIndex); } - (void)actionSheet:(UIActionSheet *)actionSheet didDismissWithButtonIndex:(NSInteger)buttonIndex { if (didDismissCallback_) didDismissCallback_((CTActionSheet *)actionSheet, buttonIndex); } @end |
使い方は
CTAlertView *alert = [[[CTAlertView alloc] initWithTitle:@"title" message:@"message" cancelButtonTitle:@"Cancel"] autorelease]; [alert setCancelButtonCallback:^(CTAlertView *alertView, NSInteger index) { // Cancel action }]; [alert addButtonWithTitle:@"Foo" callback:^(CTAlertView *alertView, NSInteger index) { // Foo action }]; [alert addButtonWithTitle:@"Bar" callback:^(CTAlertView *alertView, NSInteger index) { // Bar action }]; [alert show]; |
のようにします。キャンセルタイトルは指定しなければキャンセルボタンは作成されません。また、キャンセルボタンコールバックを指定しなくても動作します。
CTActionSheetではキャンセルボタンの指定を- (void)addCancelButtonWithTitle:(NSString *)title callback:(CTActionSheetButtonCallback)callbackで行います。
また、テストは不十分なので、バグがあればコメントよろしくです。