Last active
February 27, 2019 09:38
-
-
Save muizidn/43fb5a907be160f92bb442f977e7893d to your computer and use it in GitHub Desktop.
An Action Director handle all your UIControl behavior. In beautiful and manageable way!
This file contains hidden or 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
/// Target-Action helper. | |
final class Action<I>: NSObject { | |
private let _action: (I) -> Void | |
private let _input: I | |
private let identifier = UUID().uuidString | |
init(action: @escaping (I) -> Void, input: I) { | |
_action = action | |
_input = input | |
super.init() | |
} | |
@objc func action() { | |
_action(_input) | |
} | |
override func isEqual(_ object: Any?) -> Bool { | |
guard let action = object as? Action<I> else { | |
return false | |
} | |
return action.identifier == identifier | |
} | |
} | |
enum UIControlEvent { | |
case touchDown(UIControl) | |
case touchDownRepeat(UIControl) | |
case touchDragInside(UIControl) | |
case touchDragOutside(UIControl) | |
case touchDragEnter(UIControl) | |
case touchDragExit(UIControl) | |
case touchUpInside(UIControl) | |
case touchUpOutside(UIControl) | |
case touchCancel(UIControl) | |
case valueChanged(UIControl) | |
func add(target: Any?, action: Selector) { | |
switch self { | |
case let .touchDown(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchDown | |
) | |
case let .touchDownRepeat(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchDownRepeat | |
) | |
case let .touchDragInside(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchDragInside | |
) | |
case let .touchDragOutside(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchDragOutside | |
) | |
case let .touchDragEnter(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchDragEnter | |
) | |
case let .touchDragExit(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchDragExit | |
) | |
case let .touchUpInside(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchUpInside | |
) | |
case let .touchUpOutside(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchUpOutside | |
) | |
case let .touchCancel(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .touchCancel | |
) | |
case let .valueChanged(control): | |
control.addTarget( | |
target, | |
action: action, | |
for: .valueChanged | |
) | |
} | |
} | |
func remove(target: Any?, action: Selector?) { | |
switch self { | |
case let .touchDown(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchDown | |
) | |
case let .touchDownRepeat(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchDownRepeat | |
) | |
case let .touchDragInside(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchDragInside | |
) | |
case let .touchDragOutside(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchDragOutside | |
) | |
case let .touchDragEnter(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchDragEnter | |
) | |
case let .touchDragExit(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchDragExit | |
) | |
case let .touchUpInside(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchUpInside | |
) | |
case let .touchUpOutside(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchUpOutside | |
) | |
case let .touchCancel(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .touchCancel | |
) | |
case let .valueChanged(control): | |
control.removeTarget( | |
target, | |
action: action, | |
for: .valueChanged | |
) | |
} | |
} | |
} | |
final class ActionsDirector { | |
private var actions: Set<NSObject> = [] { | |
didSet { | |
#if DEBUG | |
print("\(self).actions.count : \(actions.count)") | |
#endif | |
} | |
} | |
@discardableResult | |
func setupAction<I>(with event: UIControlEvent, input: I, callback: @escaping (I) -> Void) -> Action<I> { | |
let action = Action<I>( | |
action: callback, | |
input: input | |
) | |
defer { | |
event.add( | |
target: action, | |
action: #selector(action.action) | |
) | |
actions.insert(action) | |
} | |
return action | |
} | |
@discardableResult | |
func removeAction<I>(event: UIControlEvent, action: Action<I>) -> Bool { | |
defer { | |
event.remove( | |
target: action, | |
action: #selector(action.action) | |
) | |
} | |
return actions.remove(action) != nil | |
} | |
} |
This file contains hidden or 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
class Custom: UIView { | |
private var action: Action<Void>! | |
func registerOnTap(completion: @escaping () -> Void) { | |
action = Action<Void>.init(action: completion, input: ()) | |
let tapGesture = UITapGestureRecognizer(target: action, action: #selector(action.action)) | |
qrImageView.addGestureRecognizer(tapGesture) | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Lets test!