Swift派发机制

作者: xgou | 来源:发表于2018-03-21 17:54 被阅读94次

Swift之所以速度比Object-c快,我觉得跟他的派发机制有关。下面我们聊聊Swift的派发机制。

派发机制分为直接派发、函数表派发、消息派发三种。

直接派发

直接派发是最快的, 不止是因为需要调用的指令集会更少, 并且编译器还能够有很大的优化空间, 例如函数内联等, 但这不在这篇博客的讨论范围. 直接派发也有人称为静态调用.然而, 对于编程来说直接调用也是最大的局限, 而且因为缺乏动态性所以没办法支持继承.

函数表派发

函数表派发是编译型语言实现动态行为最常见的实现方式. 函数表使用了一个数组来存储类声明的每一个函数的指针. 大部分语言把这个称为 “virtual table”(虚函数表), Swift 里称为 “witness table”. 每一个类都会维护一个函数表, 里面记录着类所有的函数, 如果父类函数被 override 的话, 表里面只会保存被 override 之后的函数. 一个子类新添加的函数, 都会被插入到这个数组的最后. 运行时会根据这一个表去决定实际要被调用的函数.


3.png
消息机制派发(Object-c的OO实现)

消息机制是调用函数最动态的方式. 也是 Cocoa 的基石, 这样的机制催生了 KVO, UIAppearence 和 CoreData 等功能. 这种运作方式的关键在于开发者可以在运行时改变函数的行为. 不止可以通过 swizzling 来改变, 甚至可以用 isa-swizzling 修改对象的继承关系, 可以在面向对象的基础上实现自定义派发.


2.png

Swift 没有在文档里具体写明什么时候会使用函数表什么时候使用消息机制. 唯一的承诺是使用 dynamic 修饰的时候会通过 Objective-C 的运行时进行消息机制派发。

总结起来有这么几点:

值类型总是会使用直接派发, 简单易懂

而协议和类的 extension 都会使用直接派发

NSObject 的 extension 会使用消息机制进行派发

NSObject 声明作用域里的函数都会使用函数表进行派发.

协议里声明的, 并且带有默认实现的函数会使用函数表进行派发


指定派发方式 (Specifying Dispatch Behavior)

final

final 允许类里面的函数使用直接派发. 这个修饰符会让函数失去动态性. 任何函数都可以使用这个修饰符, 就算是 extension 里本来就是直接派发的函数. 这也会让 Objective-C 的运行时获取不到这个函数, 不会生成相应的 selector.

dynamic

dynamic 可以让类里面的函数使用消息机制派发. 使用 dynamic, 必须导入 Foundation 框架, 里面包括了 NSObject 和 Objective-C 的运行时. dynamic 可以让声明在 extension 里面的函数能够被 override. dynamic 可以用在所有 NSObject 的子类和 Swift 的原声类.这就是为什么KVO的属性需要用dynamic修饰

@objc & @nonobjc

@objc 和 @nonobjc 显式地声明了一个函数是否能被 Objective-C 的运行时捕获到. 使用 @objc 的典型例子就是给 selector 一个命名空间 @objc(abc_methodName), 让这个函数可以被 Objective-C 的运行时调用. @nonobjc 会改变派发的方式, 可以用来禁止消息机制派发这个函数, 不让这个函数注册到 Objective-C 的运行时里. 我不确定这跟 final 有什么区别, 因为从使用场景来说也几乎一样. 我个人来说更喜欢 final, 因为意图更加明显.

译者注: 我个人感觉, 这这主要是为了跟 Objective-C 兼容用的, final 等原生关键词, 是让 Swift 写服务端之类的代码的时候可以有原生的关键词可以使用.

final @objc

可以在标记为 final 的同时, 也使用 @objc 来让函数可以使用消息机制派发. 这么做的结果就是, 调用函数的时候会使用直接派发, 但也会在 Objective-C 的运行时里注册响应的 selector. 函数可以响应 perform(selector:) 以及别的 Objective-C 特性, 但在直接调用时又可以有直接派发的性能.


总结

image

相关文章

  • Swift派发机制

    Swift之所以速度比Object-c快,我觉得跟他的派发机制有关。下面我们聊聊Swift的派发机制。 派发机制分...

  • 浅谈Swift派发机制

    函数的派发机制分为:静态派发(直接派发)、函数表派发、消息派发 1、Swift中所有ValueType(值类型:S...

  • iOS知识复习笔记(16)---swift相关

    一、函数的派发方式 swift函数的派发机制有三类:static直接派发(静态)派发、table函数派发,mess...

  • Swift派发机制

    Swift派发分:静态派发和动态派发 静态派发:(又叫:直接调用) 静态派发机制,同时支持值类型和引用类型;静态派...

  • Swift的函数派发

    前言 对于Swift的学者来说函数派发有很大的误区:就是认为Swift沿用Objective-C的消息派发机制,且...

  • Swift 派发机制

    此篇博客用来自我学习,来源戴铭大佬的这篇博客 Swift 派发机制 派发目的是让 CPU 知道被调用的函数在哪里。...

  • Swift 派发机制

    表格总结如下: 值类型使用直接派发 协议、类的初始化声明使用函数表派发 协议、类的 extension 使用直接派...

  • Swift 派发机制

    https://medium.com/@bakshioye/static-vs-dynamic-dispatch-...

  • Swift - 三种函数派发

    Swift 的函数派发可以分为 静态 和 动态 两种机制,而动态派发又分为 函数表派发 和 消息派发 。 Swif...

  • Swift 函数派发机制

    原文:Method Dispatch in Swift作者:Brian King 派发机制是程序判断如何去调用函数...

网友评论

    本文标题:Swift派发机制

    本文链接:https://www.haomeiwen.com/subject/vlxnqftx.html