首页 > 解决方案 > @objc 关键字扩展子类行为

问题描述

有人可以解释为什么@objc这里需要关键字来编译代码吗?

据我了解,此关键字用于工作 ObjC 消息方法分派。但这不是一个NSObject例子。

 class MyClass {
 }

 extension MyClass {
     @objc func extensionMethod() { /// THIS LINE
         print("A")
     }
 }

 class SubClass: MyClass {
     override func extensionMethod() {
         print("B")
     }
 }

关键字是否@objc也启用消息发送dynamic?或不?

标签: swiftswift4swift4.1

解决方案


关键字是否@objc也启用消息发送dynamic

通常不会。通常,@objc属性本身只是将给定的类成员暴露给 Objective-C——Swift 仍然可以使用表或静态分派来自由地分派给它。您需要标记该成员,就dynamic好像您希望 Swift 在调用它时使用消息调度一样。

但是,对于非 final@objc扩展成员,Swift 会自动将其推断为dynamic. 为什么?因为出于互操作性的原因,Swift 允许@objc扩展成员覆盖和被覆盖(很像如何覆盖子类类别中的 Obj-C 方法)。为了实现这种行为,Swift 依赖于 Obj-C 消息分发。

因此,在扩展中,@objc推断dynamic. 你不能覆盖扩展成员而不将其暴露给 Obj-C 运行时,因为扩展成员当前不能添加到 Swift 类 vtables(因为 Swift vtables 目前不能在运行时动态添加成员)。

但这不是一个NSObject例子。

在 Apple 平台上(即具有 Obj-C 互操作性的平台),所有Swift 类都暴露给 Obj-C 运行时,并且都隐式继承自一个特殊的 Obj-C 基类,称为_SwiftObject,它符合NSObjectProtocol. 因此 Swift 类能够利用消息调度,而无需继承自NSObject.


推荐阅读