我可以传递一个块作为@selector与Objective-C? [英] Can I pass a block as a @selector with Objective-C?

查看:156
本文介绍了我可以传递一个块作为@selector与Objective-C?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

是否可以为 UIButton 中的 @selector 参数传递Objective-C块?

Is it possible to pass an Objective-C block for the @selector argument in a UIButton? i.e., Is there any way to get the following to work?

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

感谢

推荐答案

是的,但是你必须使用一个类别。

Yes, but you'd have to use a category.

有点像:

@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:方法作为目标 UIControl 类别使用关联对象存储 DDBlockActionWrappers的数组。 ,因为 UIControl 不保留其目标。

  3. 我们必须确保 DDBlockActionWrappers 当对象被销毁时清理,所以我们做了一个讨厌的黑客swizzling出来 - [UIControl dealloc] 一个新的删除相关联的对象,然后调用原始的 dealloc 代码。棘手,棘手。实际上,关联对象在解除分配期间会自动清除

  1. We're using a custom "internal only" class called DDBlockActionWrapper. This is a simple class that has a block property (the block we want to get invoked), and a method that simply invokes that block.
  2. The UIControl category simply instantiates one of these wrappers, gives it the block to be invoked, and then tells itself to use that wrapper and its invokeBlock: method as the target and action (as normal).
  3. The UIControl category uses an associated object to store an array of DDBlockActionWrappers, because UIControl does not retain its targets. This array is to ensure that the blocks exist when they're supposed to be invoked.
  4. We have to ensure that the DDBlockActionWrappers get cleaned up when the object is destroyed, so we're doing a nasty hack of swizzling out -[UIControl dealloc] with a new one that removes the associated object, and then invokes the original dealloc code. Tricky, tricky. Actually, associated objects are cleaned up automatically during deallocation.

最后,在浏览器中并没有被编译。可能有一些问题,它。您的里程可能不同。

Finally, this code was typed in the browser and has not been compiled. There are probably some things wrong with it. Your mileage may vary.

这篇关于我可以传递一个块作为@selector与Objective-C?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆