UIButton block equivalent to addTarget:action:forControlEvents: method?
I just implemented this. It work's like a charm!
And it wasn't even hard.
typedef void (^ActionBlock)();
@interface UIBlockButton : UIButton {
ActionBlock _actionBlock;
}
-(void) handleControlEvent:(UIControlEvents)event
withBlock:(ActionBlock) action;
@end
@implementation UIBlockButton
-(void) handleControlEvent:(UIControlEvents)event
withBlock:(ActionBlock) action
{
_actionBlock = action;
[self addTarget:self action:@selector(callActionBlock:) forControlEvents:event];
}
-(void) callActionBlock:(id)sender{
_actionBlock();
}
@end
There is a library of blocks additions to the common Foundation/UI classes: BlocksKit. Here is the documentation.
It does not subclass UIButton, but adds UIControl category:
[button addEventHandler:^(id sender) {
//do something
} forControlEvents:UIControlEventTouchUpInside];
There is also blocks/functional additions to collections (map, filter, etc), views-related stuff and more.
NOTE: it does not play well with Swift.
Here's a working category implementation. In it's current form, this should only be used in DEBUG
. I use this category in conjunction with a function (included below) to test various bits of code when user interaction and timing are important. Again this is only for development/debug purposes and shouldn't be considered for production, hence the #ifdef DEBUG
;)
#ifdef DEBUG
#import <objc/runtime.h>
static char UIButtonBlockKey;
@interface UIButton (UIBlockButton)
- (void)handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock)block;
- (void)callActionBlock:(id)sender;
@end
@implementation UIButton (UIBlockButton)
- (void)handleControlEvent:(UIControlEvents)event withBlock:(ActionBlock)block {
objc_setAssociatedObject(self, &UIButtonBlockKey, block, OBJC_ASSOCIATION_COPY_NONATOMIC);
[self addTarget:self action:@selector(callActionBlock:) forControlEvents:event];
}
- (void)callActionBlock:(id)sender {
ActionBlock block = (ActionBlock)objc_getAssociatedObject(self, &UIButtonBlockKey);
if (block) {
block();
}
}
@end
void DSAddGlobalButton(NSString *title, ActionBlock block) {
UIButton *button = [UIButton buttonWithType:UIButtonTypeRoundedRect];
[button setTitle:title forState:UIControlStateNormal];
[button handleControlEvent:UIControlEventTouchUpInside withBlock:block];
[button sizeToFit];
[button setFrame:(CGRect){{100.0f, 100.0f}, [button frame].size}];
UIView *firstView = [[[[UIApplication sharedApplication] keyWindow] subviews] objectAtIndex:0];
[firstView addSubview:button];
}
#endif