-
-
Save desyatov/6ed83de58ca1146d85fedab461a69b12 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import Foundation | |
import UIKit | |
/** | |
* An extension for UIControl that lets you set action handlers using closures. | |
*/ | |
extension UIControl { | |
/** | |
* A map of closures, mapped as [ event : action ] . | |
*/ | |
typealias Handlers = [UInt:((UIControl) -> Void)] | |
private enum AssociatedKey { | |
static var actionHandlers = "UIControl.actionHandlers" | |
} | |
private var actionHandlers: Handlers { | |
get { | |
return objc_getAssociatedObject(self, &AssociatedKey.actionHandlers) as? Handlers ?? [:] | |
} | |
set(newValue) { | |
objc_setAssociatedObject(self, &AssociatedKey.actionHandlers, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN) | |
} | |
} | |
/** | |
* Retrieve the handler associated with the specified event for this instance | |
* if any exists, otherwise return nil. | |
*/ | |
private func getHandler(_ event: UIControl.Event) -> ((UIControl) -> Void)? { | |
return actionHandlers[event.rawValue] | |
} | |
/** | |
* Set the action for the specified event. | |
* | |
* - parameter event: The event for which to set the action. | |
* - parameter action: The action to perform when the event is raised. | |
*/ | |
public func action(_ event: UIControl.Event, _ action: @escaping (UIControl) -> Void) { | |
actionHandlers[event.rawValue] = action | |
switch event { | |
case .touchDown: | |
self.addTarget(self, action: #selector(triggerTouchDown), for: event) | |
case .touchDownRepeat: | |
self.addTarget(self, action: #selector(triggerTouchDownRepeat), for: event) | |
case .touchDragInside: | |
self.addTarget(self, action: #selector(triggerTouchDragInside), for: event) | |
case .touchDragOutside: | |
self.addTarget(self, action: #selector(triggerTouchDragOutside), for: event) | |
case .touchDragEnter: | |
self.addTarget(self, action: #selector(triggerTouchDragEnter), for: event) | |
case .touchDragExit: | |
self.addTarget(self, action: #selector(triggerTouchDragExit), for: event) | |
case .touchUpInside: | |
self.addTarget(self, action: #selector(triggerTouchUpInside), for: event) | |
case .touchUpOutside: | |
self.addTarget(self, action: #selector(triggerTouchUpOutside), for: event) | |
case .touchCancel: | |
self.addTarget(self, action: #selector(triggerTouchCancel), for: event) | |
case .valueChanged: | |
self.addTarget(self, action: #selector(triggerValueChanged), for: event) | |
case .primaryActionTriggered: | |
self.addTarget(self, action: #selector(triggerPrimaryActionTriggered), for: event) | |
case .editingDidBegin: | |
self.addTarget(self, action: #selector(triggerEditingDidBegin), for: event) | |
case .editingDidEnd: | |
self.addTarget(self, action: #selector(triggerEditingDidEnd), for: event) | |
case .editingChanged: | |
self.addTarget(self, action: #selector(triggerEditingChanged), for: event) | |
case .editingDidEndOnExit: | |
self.addTarget(self, action: #selector(triggerEditingDidEndOnExit), for: event) | |
case .allTouchEvents: | |
self.addTarget(self, action: #selector(triggerAllTouchEvents), for: event) | |
case .allEditingEvents: | |
self.addTarget(self, action: #selector(triggerAllEditingEvents), for: event) | |
case .applicationReserved: | |
self.addTarget(self, action: #selector(triggerApplicationReserved), for: event) | |
case .systemReserved: | |
self.addTarget(self, action: #selector(triggerSystemReserved), for: event) | |
case .allEvents: | |
self.addTarget(self, action: #selector(triggerAllEvents), for: event) | |
default: break | |
} | |
} | |
// selector definitions below this line | |
@objc private func triggerTouchDown() { | |
getHandler(.touchDown)?(self) | |
} | |
@objc private func triggerTouchDownRepeat() { | |
getHandler(.touchDownRepeat)?(self) | |
} | |
@objc private func triggerTouchDragInside() { | |
getHandler(.touchDragInside)?(self) | |
} | |
@objc private func triggerTouchDragOutside() { | |
getHandler(.touchDragOutside)?(self) | |
} | |
@objc private func triggerTouchDragEnter() { | |
getHandler(.touchDragEnter)?(self) | |
} | |
@objc private func triggerTouchDragExit() { | |
getHandler(.touchDragExit)?(self) | |
} | |
@objc private func triggerTouchUpInside() { | |
getHandler(.touchUpInside)?(self) | |
} | |
@objc private func triggerTouchUpOutside() { | |
getHandler(.touchUpOutside)?(self) | |
} | |
@objc private func triggerTouchCancel() { | |
getHandler(.touchCancel)?(self) | |
} | |
@objc private func triggerValueChanged() { | |
getHandler(.valueChanged)?(self) | |
} | |
@objc private func triggerPrimaryActionTriggered() { | |
getHandler(.primaryActionTriggered)?(self) | |
} | |
@objc private func triggerEditingDidBegin() { | |
getHandler(.editingDidBegin)?(self) | |
} | |
@objc private func triggerEditingChanged() { | |
getHandler(.editingChanged)?(self) | |
} | |
@objc private func triggerEditingDidEnd() { | |
getHandler(.editingDidEnd)?(self) | |
} | |
@objc private func triggerEditingDidEndOnExit() { | |
getHandler(.editingDidEndOnExit)?(self) | |
} | |
@objc private func triggerAllTouchEvents() { | |
getHandler(.allTouchEvents)?(self) | |
} | |
@objc private func triggerAllEditingEvents() { | |
getHandler(.allEditingEvents)?(self) | |
} | |
@objc private func triggerApplicationReserved() { | |
getHandler(.applicationReserved)?(self) | |
} | |
@objc private func triggerSystemReserved() { | |
getHandler(.systemReserved)?(self) | |
} | |
@objc private func triggerAllEvents() { | |
getHandler(.allEvents)?(self) | |
} | |
} | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment