Skip to content

Instantly share code, notes, and snippets.

@totocaster
Last active January 3, 2016 07:24
Show Gist options
  • Save totocaster/0ec7c6ce6466c4768bc3 to your computer and use it in GitHub Desktop.
Save totocaster/0ec7c6ce6466c4768bc3 to your computer and use it in GitHub Desktop.
Swift-y Target-Action (UIKit version)
// Swifty Target/Action
// Friday Q&A 2015-12-25
// https://www.mikeash.com/pyblog/friday-qa-2015-12-25-swifty-targetaction.html
import UIKit
class ActionTrampoline<T>: NSObject {
var action: T -> Void
init(action: T -> Void) {
self.action = action
}
@objc func action(sender: UIControl) {
action(sender as! T)
}
}
// this code just allocates a bit of memory and uses that address,
// since Swift won't guarantee `&` to point to same pointer
let NSControlActionFunctionProtocolAssociatedObjectKey = UnsafeMutablePointer<Int8>.alloc(1)
protocol NSControlActionFunctionProtocol {}
extension NSControlActionFunctionProtocol where Self: UIControl {
func addAction(events: UIControlEvents, _ action: Self -> Void) {
let trampoline = ActionTrampoline(action: action)
self.addTarget(trampoline, action: "action:", forControlEvents: events)
objc_setAssociatedObject(self, NSControlActionFunctionProtocolAssociatedObjectKey,
trampoline, .OBJC_ASSOCIATION_RETAIN)
}
}
extension UIControl: NSControlActionFunctionProtocol {}
// usage
let button = UIButton()
button.setTitle("Hello Button", forState: .Normal)
button.addAction([.TouchUpInside], { (button: UIButton) in
// use `[unowned self]` or `[weak self]` to avoid retain cycles
print("Action from \(button.titleLabel?.text)")
})
// makig test call
button.sendActionsForControlEvents([.TouchUpInside])
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment