我正在开发一个 Cocoa Touch 框架或一个动态库,它将使用 Swift 捕获用户操作。
例如当用户点击标签时,我的框架应该知道它。 为了实现这种行为,我使用方法调配。
我正在为
UITapGestureRecognizer
创建一个扩展。在这个扩展中,在 initialize
方法中,我正在调整 init :
open override class func initialize() {
guard self === UITapGestureRecognizer.self else { return }
let originalSelector = #selector(self.init(target:action:))
let swizzledSelector = #selector(swizzled_init(target:action:))
swizzling(self, originalSelector, swizzledSelector)
}
func swizzled_init(target: Any, action: Selector) {
swizzled_init(target : target,action: action)
print("swizzled_init"+action.description)
//This part is for swizzling the the action which is being provided by the developer at the time of init.
guard self === UITapGestureRecognizer.self else { return }
let originalSelector = action
let swizzledSelector = #selector(swizzled_action(sender:))
swizzling(self.classForCoder, originalSelector, swizzledSelector)
}
func swizzled_action(sender : UITapGestureRecognizer? = nil){
print("swizzled_action"+(sender?.description)!)
}
调配 init 后,我的 ViewController 中的 tap 实例为零。
let tap = UITapGestureRecognizer.init(target: self, action: #selector(buttonTapped(sender:)))
第二个问题是在 swizzled_init 方法中:
guard self === UITapGestureRecognizer.self else { return }
正在失败。
您能指导我解决这些问题吗?
这对我来说是成功的。我创建了一个能够处理各种类类型的 SDK,包括我的 UIGestureRecognizer 实现。
导入UIKit
扩展 UIGestureRecognizer { 静态函数 swizzle() { 如果让originalMethod = class_getInstanceMethod(UIGestureRecognizer.self, #selector(UIGestureRecognizer.init(target:action:))), 让 swizzledMethod = class_getInstanceMethod(UIGestureRecognizer.self, #selector(UIGestureRecognizer.swizzled_init(target:action:))) { method_exchangeImplementations(originalMethod, swizzledMethod) } }
private static var _myComputedProperty = [String:Any]()
private var targetProperty:AnyObject? {
get {
let tmpAddress = String(format: "%ptargetProperty", unsafeBitCast(self, to: Int.self))
return UIGestureRecognizer._myComputedProperty[tmpAddress] as AnyObject
}
set(newValue) {
let tmpAddress = String(format: "%ptargetProperty", unsafeBitCast(self, to: Int.self))
UIGestureRecognizer._myComputedProperty[tmpAddress] = newValue
}
}
private var actionProperty:Selector? {
get {
let tmpAddress = String(format: "%pactionProperty", unsafeBitCast(self, to: Int.self))
return UIGestureRecognizer._myComputedProperty[tmpAddress] as? Selector
}
set(newValue) {
let tmpAddress = String(format: "%pactionProperty", unsafeBitCast(self, to: Int.self))
UIGestureRecognizer._myComputedProperty[tmpAddress] = newValue
}
}
@discardableResult @objc func swizzled_init(target: AnyObject?, action: Selector?) -> Selector {
targetProperty = target
actionProperty = action
return swizzled_init(target: self, action: #selector(swizzled_action))
}
@objc dynamic func swizzled_action() {
guard let targetProperty = targetProperty, let actionProperty = actionProperty else { return }
targetProperty.performSelector(onMainThread: actionProperty, with: self, waitUntilDone: false)
NotificationCenter.default.post(name: NSNotification.Name("trackEvent"), object: nil, userInfo: ["event": "interacted with on: \(self.description)"])
}
}