swift method_exchangeImplementations 不起作用

Tor*_*ado 5 objective-c-runtime swift

快速代码如下:

func swizzleMethod()
{
    let method:Method = class_getInstanceMethod(object_getClass(self), Selector("function1"))

    self.function1()
    let swizzledMethod:Method = class_getInstanceMethod(object_getClass(self), Selector("function2"))

    method_exchangeImplementations(method, swizzledMethod)

    self.function1()


}

func function1()
{
    print("function1 log")
}
func function2()
{
    print("function2 log")

}
Run Code Online (Sandbox Code Playgroud)

它记录:

function1 log

function1 log
Run Code Online (Sandbox Code Playgroud)

///// 我的环境是基于swift的项目,xcode7.2
这个总是碰到funtion1方法体,所以我认为交换失败了,这两个方法在同一个类中,有谁知道为什么?

Tor*_*ado 7

我得到了答案,在方法名称前添加“dynamic”关键字!!!
像这样:

dynamic  func function1()
{
    print("function1 log")
}
dynamic func function2()
{
    print("function2 log")

}
Run Code Online (Sandbox Code Playgroud)

原因:
Swift 优化代码以调用直接内存地址,而不是像在 Objective-C 中那样在运行时查找方法位置。所以我们需要告诉代码 run 把它当作 Objective-C 代码。

答案详细信息:
方法调配是一种用一种方法实现替代另一种方法的技术。如果您不熟悉 swizzling,请查看此博客文章。Swift 优化代码以调用直接内存地址,而不是像在 Objective-C 中那样在运行时查找方法位置。所以默认情况下,swizzling 在 Swift 类中不起作用,除非我们:
1. 使用 dynamic 关键字禁用此优化。这是首选,也是如果代码库完全在 Swift 中最有意义的选择。
2.扩展NSObject。切勿仅针对方法 swizzling 执行此操作(改为使用 dynamic)。知道方法 swizzling 将在以 NSObject 作为其基类的现有类中工作很有用,但我们最好有选择地选择带有 dynamic 的方法。
3. 在被 swizzled 的方法上使用 @objc 注释。如果我们想要 swizzle 的方法也需要同时暴露给 Objective-C 代码,这是合适的。

感谢这篇文章:成为更好的 Swift 开发人员的 15 个技巧