Skip to content

Instantly share code, notes, and snippets.

@karambirov
Created June 15, 2022 05:18
Show Gist options
  • Save karambirov/fe4df17fca93dd490f4273a82303fbd6 to your computer and use it in GitHub Desktop.
Save karambirov/fe4df17fca93dd490f4273a82303fbd6 to your computer and use it in GitHub Desktop.
Allows to set a Swift closure to a control instead of Objective-C selector
import UIKit
public extension UIControl {
typealias OnTouchUpInside = () -> Void
private struct Constants {
static var callbackKey = "UIControl.OnTouchUpInsideAssociatedKey"
}
@objc
var onTouchUpInside: OnTouchUpInside? {
get {
if let savedObject = objc_getAssociatedObject(self, &Constants.callbackKey) as? WrappedValue {
return savedObject.block
}
return nil
}
set {
let kSelector = #selector(UIControl._uicontrol_plus_touch_up_inside_block_handler)
removeTarget(self, action: kSelector, for: .touchUpInside)
if newValue != nil {
addTarget(self, action: kSelector, for: .touchUpInside)
}
objc_setAssociatedObject(self,
&Constants.callbackKey,
WrappedValue(newValue),
objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN)
}
}
@objc private func _uicontrol_plus_touch_up_inside_block_handler() {
gtuOnTouchUpInside?()
}
private class WrappedValue: NSObject {
let block: OnTouchUpInside
init?(_ block: OnTouchUpInside?) {
guard let block = block else {
return nil
}
self.block = block
super.init()
}
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment