I'm expanding the functionality of [this SO answer][1]. [1]: http://stackoverflow.com/a/26454949/3804019 Mainly I'm focusing on: - You can add as many handlers as you want. - You can remove (i.e. cancel) the handler. - You can receive the `sender` parameter in the handler closure. - You can add "oneshot" handler. <!--- ---> import UIKit extension UIControl { private class EventHandler { let _cb: (UIControl, UIEvent) -> Void let _oneshot: Bool init(_ cb: (UIControl, UIEvent) -> Void, oneshot: Bool) { _cb = cb _oneshot = oneshot } @objc func invoke(sender: UIControl, event: UIEvent) { _cb(sender, event) if _oneshot { sender.off(unsafeAddressOf(self)) } } } typealias EventHandlerId = UnsafePointer<Void> func on<T: UIControl>(events: UIControlEvents, _ callback: (T, UIEvent) -> Void) -> EventHandlerId { assert(self.isKindOfClass(T), "The handler must receive \(NSStringFromClass(self.dynamicType)) or UIControl") return self._on(events, EventHandler({ callback($0 as T, $1) }, oneshot: false)) } func once<T: UIControl>(events: UIControlEvents, _ callback: (T, UIEvent) -> Void) -> EventHandlerId { assert(self.isKindOfClass(T), "The handler must receive \(NSStringFromClass(self.dynamicType)) or UIControl") return self._on(events, EventHandler({ callback($0 as T, $1) }, oneshot: true)) } func on(events: UIControlEvents, _ callback: () -> Void) -> EventHandlerId { return self._on(events, EventHandler({ _, _ in callback() }, oneshot: false)) } func once(events: UIControlEvents, _ callback: () -> Void) -> EventHandlerId { return self._on(events, EventHandler({ _, _ in callback() }, oneshot: true)) } private func _on(events: UIControlEvents, _ handler: EventHandler) -> EventHandlerId { let ptr = unsafeAddressOf(handler) self.addTarget(handler, action: "invoke:event:", forControlEvents: events) objc_setAssociatedObject(self, ptr, handler, objc_AssociationPolicy(OBJC_ASSOCIATION_RETAIN_NONATOMIC)) return ptr } func off(identifier: EventHandlerId) { if let handler = objc_getAssociatedObject(self, identifier) as? EventHandler { self.removeTarget(handler, action: nil, forControlEvents: .AllEvents) objc_setAssociatedObject(self, identifier, nil, 0) } } } Usage: class MyViewController:UIViewController { @IBOutlet weak var myButton:UIButton! override func viewDidLoad() { super.viewDidLoad() // add event handler let handle = myButton.on(.TouchUpInside) { (sender, event) in // `sender` is the control itself. // `event` is the UIEvent object. } // remove event handler myButton.off(handle) // event handler can be () -> Void type myButton.on(.TouchUpInside) { [unowned self] in // your work } // "oneshot" event handler myButton.once(.TouchUpInside) { // your work } } } It's working OK... But, for example: let btn = UIButton() btn.on(.TouchUpInside) { (sender: UISwitch, _) in /* ... */ } ^^^^^^^^ This compiles, but I want to make this compile time error. Currently, as a workaround, I'm doing "assertion": assert(self.isKindOfClass(T), "The handler must receive \(NSStringFromClass(self.dynamicType)) or UIControl") And, if possible, I wish the compiler could infer the type of the `sender`, like this: let btn = UIButton() btn.on(.TouchUpInside) { sender, _ in sender.setTitle("Pushed !!", forState: .Normal) } Any ideas? ---- **Added**: to reply the @nhgrif answer: Why I did **not** implement the `sender` only version like this: func on<T: UIControl>(events:UIControlEvents, _ callback: T -> Void) -> EventHandlerId { assert(self.isKindOfClass(T), "The handler must receive \(NSStringFromClass(self.dynamicType)) or UIControl") return self._on(events, EventHandler({ sender, _ in callback(sender as T) }, oneshot: true)) } That is because of a purely technical problem: It conflict with `() -> Void` version. btn.on(.TouchUpInside) { return } // OK: () -> Void btn.on(.TouchUpInside) { (sender: UIButton) in return } // OK: T -> Void btn.on(.TouchUpInside) { sender in return } // NG: () -> Void In the last case, the compiler infers the type of `sender` as `()` :( And why I declared `EventHandler` as `private`, that is I don't want users do like this: let handler = UIControl.EventHandler({ ... }, oneshot: true) btn.on(.TouchUpInside, handler) btn.on(.TouchDown, handler) btn.off(handler) With my current code, `.off()` removes the handler from `.AllEvents`, and from associated objects. There is no way to remove it from specific event. Maybe, if we do want to do that, we can remember the registered events and handle them, but It's too much I think. Moreover, for such use case, we can simply use `addTarget()` and `removeTarget()` with custom handler object.