Skip to content

Instantly share code, notes, and snippets.

@xavierLowmiller
Last active April 27, 2017 21:33
Show Gist options
  • Save xavierLowmiller/9420f3e8c595951a49b789753c197e99 to your computer and use it in GitHub Desktop.
Save xavierLowmiller/9420f3e8c595951a49b789753c197e99 to your computer and use it in GitHub Desktop.
Convenience Initializer for UIGestureRecognizer that takes a closure
import UIKit
import ObjectiveC
private typealias GestureClosure = (UIGestureRecognizer) -> Void
private var handle: UInt8 = 0
extension UIGestureRecognizer {
/**
Initialize a UIGestureRecognizer (or subclass) with a closure
- Parameter closure: Closure to be executed when the recognizer fires
- Warning: Likely leads to retain cycles if a view controller is captured
*/
public convenience init(closure: @escaping (UIGestureRecognizer) -> Void) {
self.init()
self.closure = closure
addTarget(self, action: #selector(executeGestureClosure))
}
// Private
@objc private func executeGestureClosure() {
closure?(self)
}
private var closure: GestureClosure? {
get { return loadClosure() }
set { newValue.map(storeClosure) }
}
private struct ClosureWrapper {
let closure: GestureClosure
}
private func loadClosure() -> GestureClosure? {
guard let wrapper = objc_getAssociatedObject(self, &handle)
as? ClosureWrapper else { return nil }
return wrapper.closure
}
private func storeClosure(_ closure: @escaping GestureClosure) {
let wrapper = ClosureWrapper(closure: closure)
objc_setAssociatedObject(self,
&handle,
wrapper,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment