iOS日常积累

swift 方法替换swizzing

2023-05-30  本文已影响0人  蔡胜波

最近忽然发现了一个swift的之前发布的feature,很有意思,之后开发可能用得到,记录一下。

@_dynamicReplacement(for:)

动态方法替换,需要swift版本5.1以上,这东西貌似是为了实现Xcode中swiftUI的preview而加进来的,不过既然加进来了,就肯定可以用来做其他的,举例如下。

class Person {
    dynamic func say() {
        print("hi")
    }
}

extension Person {
    @_dynamicReplacement(for: say)
    func sayA() {
        print("A1")
        say()
        print("A2")
    }
}

Person().say()
// 输出 A1   hi   A2

注意事项:

  1. 除非增加-enable-implicit-dynamic的编译标志(building setting -> swift compiler - Custom Flags -> Other Swift Flags),否则,被替换的方法需要被 dynamic 标记,不然无法通过编译
  2. 在使用OC的运行时方法替换时,想要执行原方法,应该调用sayA,但在使用@_dynamicReplacement时,直接调用say就可以了

连环替换的场景

上面的情况看起来没有什么特殊的,我们看一下连环替换的场景

class Person {
    dynamic func say() {
        print("hi")
    }
}

extension Person {
    @_dynamicReplacement(for: say)
    func sayA() {
        print("A1")
        say()
        print("A2")
    }
}

extension Person {
    @_dynamicReplacement(for: say)
    func sayB() {
        print("B1")
        say()
        print("B2")
    }
}

Person().say()

如果是OC的运行时实现方法替换,不难想象输出会是:
B1 - A1 - hi - A2 - B2
但在这里,会输出:
B1 - hi - B2
后声明的方法替换才会生效,但假如我们添加-Xfrontend-enable-dynamic-replacement-chaining这两个编译标志后,就可以得到:
B1 - A1 - hi - A2 - B2

我这里只记录一下,具体的原理和分析可以看下下面的参考链接。

参考

  1. https://www.guardsquare.com/blog/swift-native-method-swizzling
  2. https://www.desgard.com/ios/swift/2019/07/27/swift-method-swizzling.html
上一篇 下一篇

猜你喜欢

热点阅读