objective-c Swift 原生基类或 NSObject

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/24057525/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-09-03 21:16:35  来源:igfitidea点击:

Swift native base class or NSObject

objective-cswiftobjective-c-runtime

提问by Jasper Blues

I tested out some isa swizzlingwith Swift, and found that it only works when NSObject is a super-class (directly or further up), or by using the '@objc' decoration. Otherwise it will follow a static- and vtable-dispatch style, like C++.

我用 Swift测试了一些isa swizzling,发现它只在 NSObject 是超类(直接或进一步)时才有效,或者通过使用 '@objc' 装饰。否则它将遵循静态和 vtable-dispatch 风格,如 C++。

Is it normal to define a Swift class without a Cocoa/NSObject base class? If it is I'm concerned this means foregoing much of the dynamism of Objective-C, such as method interception and run-time introspection.

定义一个没有 Cocoa/NSObject 基类的 Swift 类是否正常?如果我担心,这意味着放弃了 Objective-C 的大部分活力,例如方法拦截和运行时自省。

Dynamic run-time behavior sits at the heart of features like property observers, Core Data, Aspect Oriented Programming, Higher Order Messaging, analytical & logging frameworks and so on.

动态运行时行为是属性观察器、核心数据、面向方面编程高阶消息传递、分析和日志框架等功能的核心。

Using Objective-C's style of method invocation adds around 20 machine code operands to a method call, so in certain situations (many tight calls to methods with small bodies) C++ style static and vtable dispatch can perform better.

使用Objective-C 的方法调用风格会向方法调用添加大约20 个机器代码操作数,因此在某些情况下(对具有小主体的方法的许多紧密调用)C++ 风格的静态和vtable 调度可以表现得更好。

But given the general 95-5 rule (95% of performance gains come from tuning 5% of the code), doesn't it makes sense to start with the powerful dynamic features and harden where necessary?

但是考虑到一般的 95-5 规则(95% 的性能提升来自对 5% 的代码进行调优),从强大的动态特性开始并在必要时进行强化是否有意义?

回答by Greg Parker

Swift classes that are subclasses of NSObject:

作为 NSObject 子类的 Swift 类:

  • are Objective-C classes themselves
  • use objc_msgSend()for calls to (most of) their methods
  • provide Objective-C runtime metadata for (most of) their method implementations
  • 是 Objective-C 类本身
  • 使用objc_msgSend()的调用(大部分)的方法
  • 为(大部分)方法实现提供 Objective-C 运行时元数据

Swift classes that are not subclasses of NSObject:

不是 NSObject 子类的 Swift 类:

  • are Objective-C classes, but implement only a handful of methods for NSObject compatibility
  • do not use objc_msgSend()for calls to their methods (by default)
  • do not provide Objective-C runtime metadata for their method implementations (by default)
  • 是 Objective-C 类,但仅实现了少数 NSObject 兼容性方法
  • 不要objc_msgSend()用于调用他们的方法(默认情况下)
  • 不为其方法实现提供 Objective-C 运行时元数据(默认情况下)

Subclassing NSObject in Swift gets you Objective-C runtime flexibility but also Objective-C performance. Avoiding NSObject can improve performance if you don't need Objective-C's flexibility.

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

Edit:

编辑:

With Xcode 6 beta 6, the dynamic attribute appears. This allows us to instruct Swift that a method should use dynamic dispatch, and will therefore support interception.

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

public dynamic func foobar() -> AnyObject {
}

回答by Pete

I also found that if basing a Swift class on NSObject, I saw some unexpected run-time behaviour that could hide coding bugs. Here is an example.

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

In this example, where we don'tbase on NSObject, the compiler correctly spots the error in testIncorrect_CompilerShouldSpot, reporting "... 'MyClass' is not convertible to 'MirrorDisposition'"

在这个例子中,我们基于 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
      }
  }
}

In this example, where we base on NSObject, the compiler doesn'tspot the error in testIncorrect_CompilerShouldSpot:

在这个例子中,我们基于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
      }
  }
}

I guess the moral is, only base on NSObject where you really have to!

我想道德是,只基于 NSObject 你真的必须这样做!

回答by Cezar

According to the language reference, there is no requirement for classes to subclass any standard root class, so you can include or omit a superclass as needed.

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

Note that omitting a superclass from the class declaration, doesn't assign a implicit base superclass of any kind. It defines a base class, which will effectively become the root for an independent class hierarchy.

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

From the language reference:

从语言参考:

Swift classes do not inherit from a universal base class. Classes you define without specifying a superclass automatically become base classes for you to build upon.

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

Trying to reference superfrom a class without a super class (i.e. a base class) will result in a compile time error

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

'super' members cannot be referenced in a root class

回答by Analog File

I believe that the vast majority of Swift data will not be objc. Only those parts that do need to communicate with te Objective C infrastructure will be explicitly marked as such.

我相信绝大多数 Swift 数据不会是objc. 只有那些确实需要与目标 C 基础设施通信的部分才会被明确标记为这样。

To which extent runtime introspection will be added to the language, I do not know. Method interception will likely become only possible if the method explicitly allows it. This is my guess, but only the language designers within Apple really know where they are really heading.

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

回答by wottpal

The following is copied from Apple's Swift-eBook and gives an appropriate answer to your question:

以下内容摘自 Apple 的 Swift-eBook,并为您的问题提供了适当的答案:

Defining a Base-Class

定义基类

Any class that does not inherit from another class is known as a base class.

任何不从另一个类继承的类都称为基类。

Swift classes do not inherit from a universal base class. Classes you define without specifying a superclass automatically become base classes for you to build upon.

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



Reference

参考

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

回答by gnasher729

It is normal. Look at the design goals of Swift: The goal is to make huge classes of programming problems disappear. Method swizzling is probably not one of the things that you want to do with Swift.

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