Skip to content

Instantly share code, notes, and snippets.

@NikKovIos
Last active October 1, 2020 18:16
Show Gist options
  • Save NikKovIos/5c4c759c3b0704a195d57577931c7114 to your computer and use it in GitHub Desktop.
Save NikKovIos/5c4c759c3b0704a195d57577931c7114 to your computer and use it in GitHub Desktop.
Add the block closure to the UIButton.
/// Block for addTarget
extension UIControl {
public typealias UIControlActionBlock = (_ sender: UIControl) -> Void
public class UIControlClosureWrapper {
let owner: UIControl
let actionBlock: UIControlActionBlock
let event: UIControlEvents
init(owner: UIControl,
block: @escaping UIControlActionBlock,
event: UIControlEvents) {
self.owner = owner
self.actionBlock = block
self.event = event
objc_setAssociatedObject(owner,
&ActionBlockKey,
self,
.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
@objc func fire() {
actionBlock(owner)
}
@objc func fireOnce() {
actionBlock(owner)
owner.removeActionBlock()
}
}
@discardableResult
public func addActionBlock(fireOnce: Bool = false,
for event: UIControlEvents = .touchUpInside,
_ block: @escaping UIControlActionBlock) -> UIControl.UIControlClosureWrapper {
let w = UIControlClosureWrapper(owner: self, block: block, event: event)
let selector = fireOnce ? #selector(UIControlClosureWrapper.fireOnce) : #selector(UIControlClosureWrapper.fire)
addTarget(w, action: selector, for: event)
return w
}
public func removeActionBlock(wrapper: UIControl.UIControlClosureWrapper? = nil) {
var w: UIControl.UIControlClosureWrapper
if wrapper == nil {
guard let associatedWrapper = objc_getAssociatedObject(self, &ActionBlockKey) as? UIControlClosureWrapper else { print("⚠️ UIControl -> removeActionBlock -> Can't remove action block."); return }
w = associatedWrapper
} else {
w = wrapper!
}
self.removeTarget(w, action: #selector(UIControlClosureWrapper.fire), for: w.event)
self.removeTarget(w, action: #selector(UIControlClosureWrapper.fireOnce), for: w.event)
objc_removeAssociatedObjects(w)
}
}
// or
// MARK: - Tappabale
private var kButtonBlockAssociationKey: UInt8 = 0
public extension UIButton {
class ClosureWrapper {
var closure: VoidCompletion?
init(_ closure: VoidCompletion?) {
self.closure = closure
}
}
internal var tapButtonBlock: VoidCompletion? {
get {
if let cw = objc_getAssociatedObject(self,
&kButtonBlockAssociationKey) as? ClosureWrapper {
return cw.closure
}
return nil
}
set(newValue) {
objc_setAssociatedObject(self,
&kButtonBlockAssociationKey,
ClosureWrapper(newValue),
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC)
}
}
/** Links UIButton tap (TouchUpInside) event to a block.
Example Usage:
```
button.tap {
// do something
}
```
Or
```
button.tap(doSomething)
// later
func doSomething() {
// ...
}
```
- Returns: Itself for chaining purposes
*/
@discardableResult
func didTap(_ block:@escaping () -> Void) -> UIButton {
addTarget(self, action: #selector(UIButton.tapped), for: .touchUpInside)
tapButtonBlock = block
return self
}
/** */
@objc func tapped() {
tapButtonBlock?()
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment