iOS Swift Runtime是如何工作的

31

ObjC中,它使用Messagingstatic bindingdynamic typingdynamic bindingdynamic method resolutiondynamic loadingintrospector等技术。

重要的是,核心方法objc_msgSend负责获取您正在发送的选择器和您要将其发送到的对象,并查找类方法表以确定应该处理它的确切代码。

我的关注点如下:

  1. Swift是否在运行时执行类似于ObjC的操作?

  2. Swift运行时如何找到一些对象/类方法的实现代码?

  3. ObjC中,classesobjects会被编译为一些runtime types(例如C struct)在运行时。那么这样的classesobjectsSwift中在运行时被编译成什么?

  4. Swift运行时是否有像class / meta class / isa pointer / super pointer这样的东西?


你能举个例子吗? - Ozgur Vatansever
@Boris 我回答的与 #1 和 #2 有关。关于 #3 和 #4,我确信 Swift 肯定有一些东西,但那还没有稳定下来。最初计划在 Swift 3.0 发布时稳定 ABI,但计划已经改变:https://www.infoq.com/news/2016/05/swift-3-no-stable-abi - Igor B.
1个回答

44
简言之,方法调用分为静态和动态两种类型。
1. 静态 - 在编译时确定要调用的函数地址,因此这种调用的开销类似于 C 函数调用。该机制用于私有方法或 final 类方法调用分派。
2. 动态调度是实现面向对象编程中多态概念的机制-在运行时确定要调用的函数地址。Swift 有两个子类型:
2.1. Obj-C - 如问题中所述。当对象从 NSObject 继承或调用方法具有 @objc 前缀时使用此机制。
2.2. 基于虚拟表 (类似于 C++) - 有类似的见证表。在方法调用分派期间执行的操作只是单个算术操作-根据基类见证表中的函数偏移量和对象类见证表位置计算实际函数地址。因此,与 Obj-C 相比,这是一种相对便宜的操作。这就解释了为什么“纯” Swift 接近于 C++ 性能。
如果你的方法没有使用private关键字标记,或者你的类不是final,同时你的类是纯Swift(它不继承NSObject),则会使用基于虚拟表的机制。这意味着默认情况下所有方法都是virtual
P.S. 有助于证明我对“类型”的看法的链接:

https://developer.apple.com/swift/blog/?id=27

"子类型"的解释基于我的理解。

不错的解释。静态标记的方法难道在运行时也是静态的吗? - Sam

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接