|
#import <objc/runtime.h> |
|
#import "UIButton+MOBlockCallbacks.h" |
|
|
|
static NSString *MOBlockCallbacksKey = @"com.mobiata.ButtonBlockCallbacks"; |
|
|
|
@interface MOButtonCallbackTrampoline : NSObject |
|
@property (nonatomic, assign) UIControlEvents controlEvents; |
|
@property (nonatomic, copy) MOButtonCallback callback; |
|
@property (nonatomic, strong) id token; |
|
@end |
|
|
|
@implementation MOButtonCallbackTrampoline |
|
- (void)performCallback:(id)sender |
|
{ |
|
[self callback](sender); |
|
} |
|
@end |
|
|
|
|
|
@implementation UIButton (MOBlockCallbacks) |
|
|
|
- (id)mo_addCallback:(MOButtonCallback)callback forControlEvents:(UIControlEvents)events |
|
{ |
|
if (callback == nil) |
|
{ |
|
return nil; |
|
} |
|
|
|
NSMutableArray *callbacks = objc_getAssociatedObject(self, (__bridge const void *)(MOBlockCallbacksKey)); |
|
if (callbacks == nil) |
|
{ |
|
callbacks = [[NSMutableArray alloc] init]; |
|
objc_setAssociatedObject(self, (__bridge const void *)(MOBlockCallbacksKey), callbacks, OBJC_ASSOCIATION_RETAIN); |
|
} |
|
|
|
MOButtonCallbackTrampoline *trampoline = [[MOButtonCallbackTrampoline alloc] init]; |
|
[trampoline setControlEvents:events]; |
|
[trampoline setCallback:callback]; |
|
[trampoline setToken:[[NSProcessInfo processInfo] globallyUniqueString]]; |
|
[callbacks addObject:trampoline]; |
|
|
|
[self addTarget:trampoline action:@selector(performCallback:) forControlEvents:events]; |
|
|
|
return [trampoline token]; |
|
} |
|
|
|
- (void)mo_removeCallback:(id)callbackToken |
|
{ |
|
NSMutableArray *callbacks = objc_getAssociatedObject(self, (__bridge const void *)(MOBlockCallbacksKey)); |
|
for (NSUInteger i = 0; i < [callbacks count]; i++) |
|
{ |
|
MOButtonCallbackTrampoline *trampoline = [callbacks objectAtIndex:i]; |
|
if ([[trampoline token] isEqual:callbackToken]) |
|
{ |
|
[self removeTarget:trampoline action:@selector(performCallback:) forControlEvents:[trampoline controlEvents]]; |
|
[callbacks removeObjectAtIndex:i]; |
|
break; |
|
} |
|
} |
|
} |
|
|
|
@end |