iOS Cocoa Touch 框架中的 Swizzle Tap 手势操作

问题描述 投票:0回答:1

我正在开发一个 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 }

正在失败。

您能指导我解决这些问题吗?

ios dynamic-library swizzling cocoa-touch
1个回答
0
投票

这对我来说是成功的。我创建了一个能够处理各种类类型的 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)"])
}

}

© www.soinside.com 2019 - 2024. All rights reserved.