1. ホーム
  2. objective-c

[解決済み] Objective-Cでブロックを@selectorとして渡すことはできますか?

2023-04-10 10:46:16

質問

Objective-Cのブロックを @selector の引数に UIButton ?すなわち、次のようにする方法はありますか?

    [closeOverlayButton addTarget:self 
                           action:^ {[anotherIvarLocalToThisMethod removeFromSuperview];} 
                 forControlEvents:UIControlEventTouchUpInside];

ありがとうございます。

どのように解決するのですか?

はい、しかし、カテゴリを使用する必要があります。

のようなものです。

@interface UIControl (DDBlockActions)

- (void) addEventHandler:(void(^)(void))handler 
        forControlEvents:(UIControlEvents)controlEvents;

@end

実装は少し厄介でしょう。

#import <objc/runtime.h>

@interface DDBlockActionWrapper : NSObject
@property (nonatomic, copy) void (^blockAction)(void);
- (void) invokeBlock:(id)sender;
@end

@implementation DDBlockActionWrapper
@synthesize blockAction;
- (void) dealloc {
  [self setBlockAction:nil];
  [super dealloc];
}

- (void) invokeBlock:(id)sender {
  [self blockAction]();
}
@end

@implementation UIControl (DDBlockActions)

static const char * UIControlDDBlockActions = "unique";

- (void) addEventHandler:(void(^)(void))handler 
        forControlEvents:(UIControlEvents)controlEvents {

  NSMutableArray * blockActions = 
                 objc_getAssociatedObject(self, &UIControlDDBlockActions);

  if (blockActions == nil) {
    blockActions = [NSMutableArray array];
    objc_setAssociatedObject(self, &UIControlDDBlockActions, 
                                        blockActions, OBJC_ASSOCIATION_RETAIN);
  }

  DDBlockActionWrapper * target = [[DDBlockActionWrapper alloc] init];
  [target setBlockAction:handler];
  [blockActions addObject:target];

  [self addTarget:target action:@selector(invokeBlock:) forControlEvents:controlEvents];
  [target release];

}

@end

いくつかの説明があります。

  1. というカスタム "内部専用" クラスを使用しています。 DDBlockActionWrapper . これはブロックプロパティ (呼び出したいブロック) と、そのブロックを呼び出すだけのメソッドを持つ単純なクラスです。
  2. UIControl カテゴリは単にこれらのラッパーの一つをインスタンス化し、呼び出されるブロックを与え、そしてそのラッパーとその invokeBlock: メソッドをターゲットとアクションとして使うように指示します (通常通り)。
  3. UIControl の配列を格納するために、関連するオブジェクトを使用します。 DDBlockActionWrappers というのは UIControl はターゲットを保持しないためです。 この配列は、ブロックが呼び出されることになっているときに存在することを確認するためのものです。
  4. はオブジェクトが破壊されたときにクリーンアップされるようにしなければなりません。 DDBlockActionWrappers を、関連するオブジェクトを削除する新しいものと交換し、それから元の -[UIControl dealloc] のコードを実行します。 トリッキー、トリッキー。 実は に関連付けられたオブジェクトは、割り当て解除の際に自動的にクリーンアップされます。 .

最後に、このコードはブラウザで入力されたもので、コンパイルはされていません。 おそらく、いくつか間違っている部分があると思います。 あなたのマイレージは変わるかもしれません。