NO プログラム NO LIFE

ayanamiの備忘録

[Objective-C]UIControlのイベントハンドラに引数を渡す

Cocoaの[UIControl addTarget:action:forControlEvents:]ではactionに設定するセレクタに引数を渡すことができないので、 categoryblocksを利用して、自由に定義したコールバックを渡せるようにする。

ファイル名はUIControl+Blocksとする。まずはヘッダファイルを定義。

1
2
3
4
#import <UIKit/UIKit.h>
@interface UIControl(Blocks)
- (void)addTargetWithBlocks:(void (^)())blocks forControlEvents:(UIControlEvents)forControlEvents;
@end

次に実装ファイルを定義。category内ではインスタンス変数を保持できないので、関連参照を用いてblocksをストアする。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
#import "UIControl+Blocks.h"
#import <objc/runtime.h>
@implementation UIControl(Blocks)
- (void)addTargetWithBlocks:(void (^)())blocks forControlEvents:(UIControlEvents)forControlEvents {
    objc_setAssociatedObject(self, @"key", blocks, OBJC_ASSOCIATION_COPY);
    [self addTarget:self action:@selector(callback:) forControlEvents:forControlEvents];
}
- (void)callback:(id)sender {
    void (^blocks)() = objc_getAssociatedObject(self, @"key");
    if (blocks) {
        blocks();
    }
}
@end

後は、任意のクラスでヘッダファイルをインポートすれば、[UIControl addTargetWithBlocks:forControlEvents:]が利用できる。

1
2
3
[btn addTargetWithBlocks:^{
    NSLog(@"%@", @"hoge");
} forControlEvents:UIControlEventTouchUpInside];