@objc关键字扩展子类行为

Vya*_*lav 12 swift swift4 swift4.1

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

据我所知,这个关键字用于工作ObjC消息方法调度.但这不是一个NSObject例子.

 class MyClass {
 }

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

 class SubClass: MyClass {
     override func extensionMethod() {
         print("B")
     }
 }
Run Code Online (Sandbox Code Playgroud)

@objc关键字是否启用消息调度以及dynamic?或不?

Ham*_*ish 16

@objc关键字是否启用消息调度以及dynamic

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

但是,对于非final @objc扩展成员,Swift会自动推断它dynamic.为什么?因为出于互操作性的原因,Swift允许@objc扩展成员覆盖和覆盖(就像你可以覆盖子类类别中的Obj-C方法一样).为了实现这种行为,Swift依赖于Obj-C消息调度.

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

但这不是一个NSObject例子.

在Apple平台上(即那些与Obj-C互操作的平台),所有 Swift类都暴露给Obj-C运行时,并且都隐式继承了一个特殊的Obj-C基类_SwiftObject,它被称为符合NSObjectProtocol.所以Swift类能够利用消息调度而不必继承NSObject.

  • 据我所知,@ Honey没有。在Swift 4中唯一发生变化的是,Swift不再在NSObject继承类的成员上推论@objc属性。因此,如果MyClass从NSObject继承而来,OP的示例将在Swift 3中没有显式的@objc进行编译(因为编译器会推断出@objc)。但是现在编译器需要一个显式的@objc,以使您清楚地将其暴露给Obj-C,而不管NSObject继承如何。 (2认同)