【问题标题】:Swift - method swizzlingSwift - 方法调配
【发布时间】:2018-09-17 11:04:28
【问题描述】:

这是用 Objective-C 编写的方法调配代码。我很难在 Swift 中转换它。

void MPApplicationDidRegisterForRemoteNotificationsWithDeviceToken(id self, SEL _cmd, UIApplication *application, NSData *deviceToken) {
    [[MPPush shared] appRegisteredForRemoteNotificationsWithDeviceToken:deviceToken];

    IMP original = [MPAppDelegateProxy originalImplementation:_cmd class:[self class]];
    if (original)
        ((void(*)(id, SEL, UIApplication *, NSData*))original)(self, _cmd, application, deviceToken);
}  

Swiftify 没有正确转换上述代码。

我尝试这样做,但我不确定如何在 Swift swizzling 方法中传递参数和使用上述参数。这是我在 Swift 中转换上述内容的失败尝试(代码甚至无法编译):

var MPApplicationDidRegisterForRemoteNotificationsWithDeviceToken: Void {
        //     TODO:   MPPush.shared.app

        let original = MPAppDelegateProxy.proxyAppDelegate.originalImplementation(selector: cmd, forClass: type(of: self))
    }(self: Any, _cmd: Selector, application: UIApplication, deviceToken: Data)

【问题讨论】:

  • @Cristik:我不能用 Swift 做这个吗?
  • 这个方法定义在什么类上?
  • @Cristik :因为它不是函数。 Objective-C 函数以 - 开头
  • @Cristik :那么,这应该只是一个简单的 Swift 函数吗?

标签: ios objective-c swift isa-swizzling


【解决方案1】:

扩展你的课程:

extension YourClassName {
    static let classInit: () -> () = {
        let originalSelector = #selector(originalFunction)
        let swizzledSelector = #selector(swizzledFunction)
        swizzle(YourClassName.self, originalSelector, swizzledSelector)
    }

    @objc func swizzledFunction() {
        //Your new implementation
    }
}

您的类 (YourClassName) 应该继承自 NSObject 并且 originalSelector 应该是 dynamic 方法。

swizzle 是一个交换实现的闭包:

private let swizzle: (AnyClass, Selector, Selector) -> () = { fromClass, originalSelector, swizzledSelector in
    guard 
        let originalMethod = class_getInstanceMethod(fromClass, originalSelector),
        let swizzledMethod = class_getInstanceMethod(fromClass, swizzledSelector)
        else { return }
    method_exchangeImplementations(originalMethod, swizzledMethod)
}

您可以在您要进行调配的类中定义swizzle。例如AppDelegate 类定义。然后在AppDelegate.init() 中进行调配:

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    override init() {
        super.init()
        YourClassName.classInit()
    }
}

示例

这里是一个 swizzling 的具体例子,它exchanges the implementation 的两个方法都接受一个参数:

class Example: NSObject {
    @objc dynamic func sayHi(to name: String) {
        print("Hi", name)
    }
}

extension Example {
    public class func swizzleMethod() {
        guard
            let originalMethod = class_getInstanceMethod(Example.self, #selector(Example.sayHi(to:))),
            let swizzledMethod = class_getInstanceMethod(Example.self, #selector(Example.sayHello(to:)))
            else { return }
        method_exchangeImplementations(originalMethod, swizzledMethod)
    }
    @objc func sayHello(to name: String) {
        print("Hello", name)
    }
}

Example.swizzleMethod()

let a = Example()
a.sayHi(to: "Nitish")        //Hello Nitish

【讨论】:

  • 你能告诉我你的答案吗?我在转换和调用 MPApplicationDidRegisterForRemoteNotificationsWithDeviceToken 时遇到困难
  • 我添加了一个 swizzling 方法的具体示例
猜你喜欢
  • 2021-12-29
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2022-11-09
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多