【问题标题】:how to swizzle method of class with some customized method through extension如何通过扩展使用一些自定义方法来调整类的方法
【发布时间】:2020-06-07 04:41:41
【问题描述】:

我在玩调酒。我已经编写了这段代码来交换具有扩展名的类的方法的实现。

@objc class A: NSObject {
    @objc func name() {
        print("this is class A")
    }
}

extension A {
    @objc func myName() {
        self.myName()
        print("this is my extension version of A")
    }
}

@objc class B: A {
    @objc override func name() {
        super.name()
    }

    @objc override func myName() {
        super.myName()
    }
}

// swizzling name and myName
let originalSelector = #selector(A.name)
let swizzledSelector = #selector(A.myName)

guard let swizzledMethod = class_getInstanceMethod(A.self, swizzledSelector) else {
    fatalError()
}

if let originalMethod = class_getInstanceMethod(A.self, originalSelector)  {
    method_exchangeImplementations(originalMethod, swizzledMethod)
    print("replaced")
}

现在我运行这段代码来测试它:

let b = B()
print("-----")
b.name()
print("-----")
b.myName()

我期望这个输出:

replaced
-----
this is class A
this is my extension version of A
-----
this is class A

但我在日志中实际看到的是这样的:

replaced
-----
this is class A
-----
this is class A

我在做什么或期待错了什么?

【问题讨论】:

    标签: ios objective-c swift swizzling


    【解决方案1】:

    参考swift method_exchangeImplementations not work

    通过添加 dynamic 声明修饰符,swizzling 可以正常进行。没有这个,对 method_exchangeImplementations() 的调用不会产生预期的效果。有关动态调度的更多信息,请参阅https://swiftunboxed.com/interop/objc-dynamic/

    像这样:

    @objc dynamic func name() {
        print("this is class A")
    }
    

    【讨论】:

    • “调用 ... 无效”——您可能希望对此进行限定。该调用具有效果——动态查找的方法实现被交换——这将从 Objective-C 中看到。然而 Swift 将(可能?)避免动态调度并编译对原始方法实现的直接调用除非存在dynamic 关键字。
    • @BenW tnx,你是对的,它按我的预期工作。那么像UIViewController中的viewDidAppear这样的函数都有这个动态定义吗?
    猜你喜欢
    • 2014-10-12
    • 1970-01-01
    • 1970-01-01
    • 2016-10-21
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-09-10
    • 1970-01-01
    相关资源
    最近更新 更多