// Register listener, keep the reference to unregister the listener let listener = button.listenOnce({ print("I will say this every time you tap the button") }, for: [.touchUpInside])
// … later … button.unlisten(listener)
// Listen once for the control events, automatically unlisten when the block is performed button.listenOnce({ print("I will only say this once") }, for: [.touchUpInside, .touchDragExit])
/// Container class for closures, so that closure can be stored as an associated object finalclassClosureContainer<T: Closurable> { var closure: (T) -> Void var sender: T? init(closure: @escaping (T) -> Void, sender: T?) { self.closure = closure self.sender = sender } // method for the target action, visible to UIKit classes via @objc @objcfuncprocessHandler() { iflet sender = sender { closure(sender) } } // target action var action: Selector { return#selector(processHandler) } }
接下来我们来实现我们的协议
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15
// ************** Protocol *************** /// Closurable protocol protocolClosurable: class {} // restrict protocol to only classes => can refer to the class instance in the protocol extension extensionClosurable { // Create container for closure, store it and return it funcgetContainer(forclosure: @escaping (Self) -> Void) -> ClosureContainer<Self> { weakvar weakSelf =self let container =ClosureContainer(closure: closure, sender: weakSelf) // store the container so that it can be called later, we do not need to explicitly retrieve it. objc_setAssociatedObject(self, Unmanaged.passUnretained(self).toOpaque(), container, .OBJC_ASSOCIATION_RETAIN_NONATOMIC) return container } }