swift 方法替换swizzing

最近忽然发现了一个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
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

友情链接更多精彩内容