Swift本机基类或NSObject

时间:2014-06-05 10:19:07

标签: objective-c swift objective-c-runtime

我用Swift测试了一些isa swizzling,发现它只适用于NSObject是超类(直接或更高级),或者使用' @ objc'装饰。否则它将遵循静态和vtable-dispatch样式,如C ++。

在没有Cocoa / NSObject基类的情况下定义Swift类是否正常?如果它是我所关心的,这意味着要超越Objective-C的大部分动力,例如方法拦截和运行时内省。

动态运行时行为是财产观察者,核心数据,Aspect Oriented ProgrammingHigher Order Messaging,分析和&等功能的核心。日志框架等。

使用Objective-C的方法调用样式会在方法调用中添加大约20个机器代码操作数,因此在某些情况下(对具有小型主体的方法的许多严格调用)C ++样式静态和vtable调度可以更好地执行。

但是考虑到一般的95-5规则( 95%的性能增益来自调整5%的代码),从强大的动态功能开始并没有意义必要时变硬吗?

6 个答案:

答案 0 :(得分:98)

作为NSObject的子类的Swift类:

  • 是Objective-C类本身
  • 使用objc_msgSend()来调用(大部分)他们的方法
  • 为(大多数)方法实现提供Objective-C运行时元数据

不是NSObject的子类的Swift类:

  • 是Objective-C类,但只实现了少数NSObject兼容性方法
  • 不要使用objc_msgSend()来调用其方法(默认情况下)
  • 不为其方法实现提供Objective-C运行时元数据(默认情况下)

在Swift中对NSObject进行子类化可以获得Objective-C运行时灵活性以及Objective-C性能。如果您不需要Objective-C的灵活性,避免使用NSObject可以提高性能。

修改

使用Xcode 6 beta 6,会出现动态属性。这允许我们指示Swift方法应该使用动态分派,因此将支持拦截。

public dynamic func foobar() -> AnyObject {
}

答案 1 :(得分:13)

我还发现,如果在NSObject上建立Swift类,我会看到一些意外的运行时行为,可能会隐藏编码错误。这是一个例子。

在这个例子中,我们基于NSObject,编译器正确地发现了testIncorrect_CompilerShouldSpot中的错误, 报告" ...' MyClass'不能兑换为MirrorDisposition'"

class MyClass {
  let mString = "Test"

  func getAsString() -> String {
    return mString
  }

  func testIncorrect_CompilerShouldSpot() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject == myString) {
        // Do something
      }
  }

  func testCorrect_CorrectlyWritten() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject.getAsString() == myString) {
        // Do something
      }
  }
}

在这个基于 NSObject 的示例中,编译器没有发现testIncorrect_CompilerShouldSpot中的错误:

class myClass : NSObject {
  let mString = "Test"

  func getAsString() -> String {
    return mString
  }

  func testIncorrect_CompilerShouldSpot() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject == myString) {
        // Do something
      }
  }

  func testCorrect_CorrectlyWritten() {
    var myString = "Compare to me"
      var myObject = MyClass()
      if (myObject.getAsString() == myString) {
        // Do something
      }
  }
}

我认为道德是,只有你真正需要的NSObject!

答案 2 :(得分:12)

根据语言参考,不要求类继承任何标准根类,因此您可以根据需要包含或省略超类。

请注意,省略类声明中的超类,不会分配任何类型的隐式基类。它定义了一个基类,它将有效地成为独立类层次结构的根。

来自语言参考:

  

Swift类不从通用基类继承。给你上课   定义而不指定超类自动成为基类   你可以上课。

尝试从没有超类(即基类)的类中引用super将导致编译时错误

'super' members cannot be referenced in a root class

答案 3 :(得分:1)

我相信绝大多数Swift数据都不会是objc。只有那些需要与Objective C基础架构进行通信的部分才会明确标记为这样。

我不知道运行时内省会在何种程度上添加到语言中。只有在方法明确允许的情况下,方法拦截才有可能实现。这是我的猜测,但只有Apple内部的语言设计师才真正了解他们的目标。

答案 4 :(得分:1)

以下内容是从Apple的Swift-eBook中复制而来,并为您的问题提供了合适的答案:

定义基类

任何不从其他类继承的类都称为基类。

Swift类不从通用基类继承。您定义的类而不指定超类会自动成为您构建的基类。


参考

https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Inheritance.html#//apple_ref/doc/uid/TP40014097-CH17-XID_251

答案 5 :(得分:-6)

这很正常。看看Swift的设计目标:目标是让大量的编程问题消失。方法调配可能不是你想用Swift做的事情之一。