Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
@import UIKit;
@interface UIButton(Magic)
- (void)onTouchUpInside:(void(^)(UIButton *button))block NS_SWIFT_NAME(onTouchUpInside(_:));
@end
#import "UIButton+Magic.h"
#import <objc/runtime.h>
// A key for the associated object that contains the action block.
static void *_magicActionName = &_magicActionName;
// Declare the _magicAction selector to avoid a compiler warning
@interface NSObject(Magic)
- (IBAction)_magicAction:(id)sender;
@end
// The implementation for the _magicAction selector
void _magicAction(id self, SEL _cmd, id sender) {
void(^block)(UIButton *button) = objc_getAssociatedObject(self, _magicActionName);
block(self);
}
@implementation UIButton(Magic)
- (void)onTouchUpInside:(void(^)(UIButton *button))block
{
Class klass = [self class];
NSString *klassName = NSStringFromClass(klass);
NSString *newKlassName = [NSString stringWithFormat:@"_Magic%@", klassName];
const char *newKlassCName = [newKlassName UTF8String];
SEL _magicActionSelector = @selector(_magicAction:);
// Define new class
Class newKlass = objc_getClass(newKlassCName);
if (newKlass == nil) {
newKlass = objc_allocateClassPair([self class], newKlassCName, 0);
class_addMethod(newKlass, _magicActionSelector, (IMP)_magicAction, "@");
objc_registerClassPair(newKlass);
}
// Go
object_setClass(self, newKlass);
objc_setAssociatedObject(self, _magicActionName, block, OBJC_ASSOCIATION_COPY);
[self addTarget:self action:_magicActionSelector forControlEvents:UIControlEventTouchUpInside];
}
@end
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
var counter = 0
button.onTouchUpInside { button in
counter += 1
button?.setTitle("Taps: \(counter)", for: .normal)
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment