Skip to content

Instantly share code, notes, and snippets.

@scelis
Last active December 17, 2015 13:59
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save scelis/5620818 to your computer and use it in GitHub Desktop.
Save scelis/5620818 to your computer and use it in GitHub Desktop.
Adding block callback functionality to UIButton.
#import <UIKit/UIKit.h>
typedef void (^MOButtonCallback)(id sender);
@interface UIButton (MOBlockCallbacks)
// Adds a block callback for a set of UIControlEvents. This method returns an opaque token which
// can be used to remove the callback.
- (id)mo_addCallback:(MOButtonCallback)callback forControlEvents:(UIControlEvents)events;
// Removes a callback registered in addCallback:forControlEvents:.
- (void)mo_removeCallback:(id)callbackToken;
@end
#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
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment