使い方はこんなイメージ:
ActionSheetBlocksExtension* sheet = [[ActionSheetBlocksExtension alloc]
initWithTitle:@"Action sheet sample"
didClick:^(UIActionSheet* actionSheet, NSInteger buttonIndex) {
NSLog(@"[1] index %d: %@", buttonIndex, actionSheet);
}
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:@"Destructive"
otherButtonTitles:@"Other-11", @"Other-12", @"Other-13", nil];アーキテクチャ
UIActionSheet のサブクラスを作り、このクラスで UIActionSheetDelegate を実装する。できればカテゴリで行きたかったが、Delegate先になるのと Blockを保持する必要があったのでサブクラスとした。
実装
今回は ActionSheetBlocksExtension という UIActionSheet のサブクラスを作った。
@interface ActionSheetBlocksExtension : UIActionSheet <UIActionSheetDelegate> {
void (^didClickBlock_)(UIActionSheet*, NSInteger);
}
- (id)initWithTitle:(NSString *)title
didClick:(void (^)(UIActionSheet*, NSInteger))block
cancelButtonTitle:(NSString *)cancelButtonTitle
destructiveButtonTitle:(NSString *)destructiveButtonTitle
otherButtonTitles:(NSString *)firstOtherTitle,...;
@enddidClickBlock_ は引数で渡される Block を格納するためのメンバ変数。
実装:
#pragma mark -
#pragma mark Initialization & deallocation
- (id)initWithTitle:(NSString *)title
didClick:(void (^)(UIActionSheet*, NSInteger))block
cancelButtonTitle:(NSString *)cancelButtonTitle
destructiveButtonTitle:(NSString *)destructiveButtonTitle
otherButtonTitles:(NSString *)firstOtherTitle,...
{
self = [super initWithTitle:title
delegate:self
cancelButtonTitle:nil
destructiveButtonTitle:nil
otherButtonTitles:nil];
if (self) {
didClickBlock_ = [block retain];
int index = 0;
if (destructiveButtonTitle) {
[self addButtonWithTitle:destructiveButtonTitle];
self.destructiveButtonIndex = index;
index++;
}
if (firstOtherTitle) {
[self addButtonWithTitle:firstOtherTitle];
index++;
va_list args;
va_start(args, firstOtherTitle);
NSString* title;
while (title = va_arg(args, NSString*)) {
[self addButtonWithTitle:title];
index++;
}
va_end(args);
}
[self addButtonWithTitle:cancelButtonTitle];
self.cancelButtonIndex = index;
}
return self;
}
- (void) dealloc
{
[didClickBlock_ release];
[super dealloc];
}
#pragma mark -
#pragma mark UIActionSheetDelegate
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
didClickBlock_(actionSheet, buttonIndex);
}特に難しいことはやっていない。初期化で渡された blockを didClickBlock_ へ格納しておき、ボタンが押された時に呼び出している。
UIActionSheet のサブクラスの初期化については前回取り上げたのでそちらを参照のこと。
サンプル
これを組み込んだサンプルを作ってみた。呼び出し側のコードはこんな感じ。
- (IBAction)openSheet1:(id)sender
{
ActionSheetBlocksExtension* sheet = [[ActionSheetBlocksExtension alloc]
initWithTitle:@"Action sheet sample"
didClick:^(UIActionSheet* actionSheet, NSInteger buttonIndex) {
NSLog(@"[1] index %d: %@", buttonIndex, actionSheet);
}
cancelButtonTitle:@"Cancel"
destructiveButtonTitle:@"Destructive"
otherButtonTitles:@"Other-11", @"Other-12", @"Other-13", nil];
[sheet autorelease];
[sheet showInView:self.view];
}Blocks内の処理は、押されたボタンのindexとUIActionSheetのインスタンスをデバッグ出力している。さて実行してみよう。テスト用に3つの UIActionSheet を作るようにしてみた。
UIActionSheetの表示
ボタンを押すと Blocksで定義したコードが呼び出されているのがわかる。
[67822:207] [1] index 4: <ActionSheetBlocksExtension: 0x5d14ab0; baseClass = UIActionSheet; frame = (0 124; 320 336); opaque = NO; layer = <CALayer: 0x5d0fa80>>
ソースコード
GitHubからどうぞ。
ActionSheetUsingBlocks at 2010-07-27 from xcatsan's iOS-Sample-Code - GitHub
参考情報
- Blocks Programming Topics: Getting Started with Blocks
- iPhone Dev Center 提供の Blocks解説
その他
Blocks は不慣れなので問題があるかもしれません。ツッコミがあれば是非コメントにどうぞ。
なお @marvelph @gnue のツイートが参考になりました。ありがとうございました。





Responses
Leave a Response