例:
- (void)showActionSheet
{
UIActionSheet* as = [[UIActionSheet alloc] initWithTitle:@"title" delegate:self cancelButtonTitle:@"cancell" destructiveButtonTitle:@"destruct" otherButtonTitles:@"btn1", @"btn2", nil ];
[as showInView:self.view];
[as autorelease];
}
- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
switch(actionSheet.tag) {
case MSG_CONFIRM_TAG: {
switch (buttonIndex) {
case 1:
// destruct break;
case 2:
// cancell break;
case 3:
//btn1 default:
break;
}
}
break;
default::
break;
}
}
表示するロジックと、アクションが別々に書かれていて、直感的なコードではない。
また、異なるUIActionSheetでも同じdelegate先になってしまう(書き方しだいですが)
iOS4からはBlocksというコールバックのような仕組みが準備されていて、それを使えば、表示部分と、アクションされた部分を一カ所で記述できる。
例1:
- (void)showActionSheet{ UIActionSheet* as = [[UIActionSheet alloc] initWithTitle:@"sample" block:^(NSInteger buttonIndex){ switch (buttonIndex) { case 1: // destruct break; case 2: // cancell break; case 3: //btn1 default: break; } } cancelButtonTitle:@"cancell" destructiveButtonTitle:@"destruct" otherButtonTitles:@"oth1", @"oth2", nil]; [as showInView:self.view]; [as autorelease];}例2:
- (void)showActionSheet
{
UIActionSheet* as = [[UIActionSheet alloc] init];
as.title = @"sample";
[as addButtonWithTitle:@"btn1" withBlock:^{
// btn1
}];
[as addButtonWithTitle:@"btn2" withBlock:^{
// btn2
}];
[as addButtonWithTitle:@"cancel" withBlock:^{
// cancell
}];
[as setCancelButtonIndex:2];
[as showInView:self.view];
[as autorelease];
}
今回はcategoryとして生成しましたが、もちろんサブクラス化しても対応できます
- initializeと、ボタンを追加する(addButtonWithTitle)にそれぞれblockを受け取る
- delegate先のblock格納先として、UIActionSheetCallbackを作成
UIActionSheet+Blocks.h
@interface UIActionSheet (Blocks)
typedef void (^UIActionSheetCallback_t)(NSInteger buttonIndex);
typedef void (^UIActionSheetButtonCallback_t)(void);
- (id)initWithTitle:(NSString *)title block:(UIActionSheetCallback_t)block cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... NS_REQUIRES_NIL_TERMINATION;
- (NSInteger)addButtonWithTitle:(NSString *)title withBlock:(UIActionSheetButtonCallback_t)block;
@end
@interface UIActionSheetCallback : NSObject <UIActionSheetDelegate> {
UIActionSheetCallback_t callback; NSMutableDictionary* buttonCallbacks;
}
@property (nonatomic, copy) UIActionSheetCallback_t callback;@property (nonatomic, retain) NSMutableDictionary* buttonCallbacks;
- (id)initWithCallback:(UIActionSheetCallback_t) callback;
@end
UIActionSheet+Blocks.m
#import "UIActionSheet+Blocks.h"
@implementation UIActionSheet (Blocks)
- (id)initWithTitle:(NSString *)title block:(void(^)(NSInteger))block cancelButtonTitle:(NSString *)cancelButtonTitle destructiveButtonTitle:(NSString *)destructiveButtonTitle otherButtonTitles:(NSString *)otherButtonTitles, ... {
self = [self initWithTitle:title delegate:nil cancelButtonTitle:cancelButtonTitle destructiveButtonTitle:destructiveButtonTitle otherButtonTitles:nil]; if (self) {
self.delegate = [[[UIActionSheetCallback alloc] initWithCallback:block] autorelease];
va_list args;
va_start(args, otherButtonTitles);
for (NSString *arg = otherButtonTitles; arg != nil; arg = va_arg(args, NSString*)) {
[self addButtonWithTitle:arg];
}
va_end(args);
}
return self;}
- (NSInteger)addButtonWithTitle:(NSString *)title withBlock:(void(^)(void))block {
if (!self.delegate) {
self.delegate = [[[UIActionSheetCallback alloc] init] autorelease];
}
NSInteger index = [self addButtonWithTitle:title];
[((UIActionSheetCallback*)self.delegate).buttonCallbacks setObject:[[block copy] autorelease] forKey:[NSNumber numberWithInteger:index]];
return index;
}
@end
@implementation UIActionSheetCallback
@synthesize callback;@synthesize buttonCallbacks;
- (void)_init {
self.buttonCallbacks = [NSMutableDictionary dictionary]; [self retain];
}
- (id)init {
if (self = [super init]) {
[self _init];
}
return self;}
- (id)initWithCallback:(UIActionSheetCallback_t)aCallback {
if(self = [super init]) {
self.callback = aCallback;
[self _init];
}
return self;}
// UIAlertView の delegate メソッド- (void)actionSheet:(UIActionSheet *)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if(callback) callback(buttonIndex);
UIActionSheetButtonCallback_t buttonCallback = [buttonCallbacks objectForKey:[NSNumber numberWithInteger:buttonIndex]]; if (buttonCallback)
buttonCallback();
[self release];
}
- (void)dealloc {
self.callback = nil;
self.buttonCallbacks = nil; [super dealloc];
}
@end
コードはこちらから
https://github.com/hrk-ys/ios-blocks
0 件のコメント:
コメントを投稿