Skip to content

Instantly share code, notes, and snippets.

@sanekgusev
Created September 2, 2016 10:17
Show Gist options
  • Save sanekgusev/e01af2c1808eefa741bda7d17eb0e638 to your computer and use it in GitHub Desktop.
Save sanekgusev/e01af2c1808eefa741bda7d17eb0e638 to your computer and use it in GitHub Desktop.
TargetActionClosureAdapter
import UIKit
import ObjectiveC.runtime
private class TargetActionClosureAdapter<T : AnyObject> {
typealias Closure = (sender: T!) -> Void
private let closure: Closure
private init() {
closure = {_ in }
}
init(_ closure: Closure) {
self.closure = closure
}
var actionSelector: Selector {
return #selector(self.dynamicType.action(_:))
}
@objc
private func action(sender: AnyObject) {
closure(sender: sender as? T)
}
}
private var associatedObjectKey: Int = 0
private extension TargetActionClosureAdapter {
private func attachToObject(object: AnyObject) {
objc_setAssociatedObject(object, &associatedObjectKey, self, .OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
public extension UIControl {
@objc(sgv_addHandlerForControlEvents:withBlock:)
public func addHandlerForControlEvents(controlEvents: UIControlEvents, handler: (sender: UIControl!) -> Void) {
let adapter = TargetActionClosureAdapter(handler)
addTarget(adapter, action: adapter.actionSelector, forControlEvents: controlEvents)
adapter.attachToObject(self)
}
}
public extension UIBarButtonItem {
@objc(sgv_addHandlerWithBlock:)
public func addHandler(handler: (sender: UIBarButtonItem!) -> Void) {
let adapter = TargetActionClosureAdapter(handler)
target = adapter
action = adapter.actionSelector
adapter.attachToObject(self)
}
}
public extension UIAccessibilityCustomAction {
@objc(sgv_addHandlerWithBlock:)
public func addHandler(handler: (sender: UIAccessibilityCustomAction!) -> Void) {
let adapter = TargetActionClosureAdapter(handler)
target = adapter
selector = adapter.actionSelector
adapter.attachToObject(self)
}
}
public extension UIGestureRecognizer {
@objc(sgv_addHandlerWithBlock:)
public func addHandler(handler: (sender: UIGestureRecognizer!) -> Void) {
let adapter = TargetActionClosureAdapter(handler)
addTarget(adapter, action: adapter.actionSelector)
adapter.attachToObject(self)
}
}
public extension CADisplayLink {
@objc(sgv_initWithHandlerBlock:)
public convenience init(handler: (sender: CADisplayLink!) -> Void) {
let adapter = TargetActionClosureAdapter(handler)
self.init(target: adapter, selector: adapter.actionSelector)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment