我可以传递一个块作为@selector与Objective-C? [英] Can I pass a block as a @selector with Objective-C?
本文介绍了我可以传递一个块作为@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
:
- 我们使用了一个名为
DDBlockActionWrapper
的自定义这是一个具有块属性(我们想要调用的块)的简单类,以及一个简单调用该块的方法。 -
UIControl
类别简单地实例化这些包装器之一,给它的被调用的块,然后告诉自己使用该包装器和它的
invokeBlock:
方法作为目标UIControl
类别使用关联对象存储DDBlockActionWrappers的数组。
,因为UIControl
不保留其目标。 -
我们必须确保实际上,关联对象在解除分配期间会自动清除。DDBlockActionWrappers
当对象被销毁时清理,所以我们做了一个讨厌的黑客swizzling出来- [UIControl dealloc]
一个新的删除相关联的对象,然后调用原始的dealloc
代码。棘手,棘手。
- 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. - 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 itsinvokeBlock:
method as the target and action (as normal). - The
UIControl
category uses an associated object to store an array ofDDBlockActionWrappers
, becauseUIControl
does not retain its targets. This array is to ensure that the blocks exist when they're supposed to be invoked. We have to ensure that theActually, associated objects are cleaned up automatically during deallocation.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 originaldealloc
code. Tricky, tricky.
最后,在浏览器中并没有被编译。可能有一些问题,它。您的里程可能不同。
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屋!
查看全文