iOS_Swift函数派发机制

这篇具有很好参考价值的文章主要介绍了iOS_Swift函数派发机制。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

前言:
函数调用机制是程序判断使用哪种途径去调用一个函数的机制,即 CPU 在内存中找到该函数地址并调用的过程。
了解函数的调用机制,对于写出高性能代码来说十分有必要。


1.Swift 函数派发类型

派发效率从高到底:Static dispatch > Table dispatch > Message dispatch

1.1 static dispatch

Static dispatch 静态派发,即直接地址调用。这个函数指针在编译、链接完成后就确定了,存放在代码段。
优点:派发速度最快,因为需要调用的指令集少,且编译器还有很大的优化空间(如:函数内敛 inline)。
缺点:局限也是最大的,因为缺乏动态性,所以没法支持继承。

1.2 table dispatch

Table dispatch 函数表派发,是编译型语言实现动态行为最常见的实现方式。函数表使用一个数组来存储类声明的每个函数的指针。大部分语言把这个称之为 Virtual Table 虚函数表,Swift 里称为 Witness Table
每个类维护一个虚函数表,记录着类的所有函数。如果被 override 的话,表里只会保存 override 后的函数。子类新增函数会被插到这个数组的最后,没有位置可以让 extension 安全的插入函数。
优点:可扩展
缺点:速度慢,编译器对某些含有副作用的函数无法优化

1.3 objc_msgSend

基于 Objc RunTime 实现,沿着实例的 isa 指针进行查找,找不到最后还有3次拯救机会。详细可见:iOS_Objective-C 消息发送(消息查找 及 消息转发)过程
优点:最动态的方式,可以实现 KVO、UIAppearance 和 CoreData 等功能。可在运行时改变函数行为。不只可以通过 swizzling 来改变,甚至可以用 isa-swizzling 修改对象继承关系,可以在面向对象基础上实现自定义派发
确定:速度最慢


2.派发类型识别

2.1 Struct / Enum

StructEnum 为值类型,不支持继承,它不需要一个 Table 来记录方法信息。所以它的方法调用(包括协议方法),都是静态派发的。

2.2 Class

对于一个 pure swift class:

  • final 修饰的 和 extension 的函数:不可被继承和重写,所以都是静态派发。
  • 其他的函数:以 Table 的机制来查找调用的。

2.3 Class - Extension

extension 中的方法和属性无法继承和重写,只属于当前类,所以是静态派发的。

2.4 NSObject Subclass

  • final 修饰的函数:同 Class
  • dynamic 修饰的 和 extension 的 函数:通过 objc_msgSend 方式派发

以上都是在没有编译器优化的情况下的派发方式,在有优化的情况下,编译器会尽可能地将方法变成静态派发 ,有的方法甚至会就地展开,变成 inline 的形式,以便提升性能。

2.5 Protocol 对象

无论真实对象是值类型还是引用类型,都使用 Table dispatch


2.6 修饰符

2.6.1 @objc/@nonobjc:

@objc/@nonobjc 只是修改对 objc 的可见性,并不会更改其派发方式。默认依旧是 Table dispatch
@objc:是将是 swift 中 继承自 NSObject 类的函数暴露给 OC。原理:生成两个函数引用,一个给 swift 调用,一个给 objc 调用。
@nonobjc:隐藏对 objc 的可见性,依然使用 Table dispatch。

2.6.2 dynamic:

dynamic 强制使用消息派发,可以动态修改。
修饰属性实现 KVO,否则 setter 会走直接派发,无法触发 KVO。

2.6.3 @inline:

@inline 指定编译器进行内敛优化。

使用建议:

  • 默认:编译器自己决定要不要使用 inline 进行优化
  • @inline(never):永远不要使用内敛优化。函数特别长且不想增大包体积时使用。
  • @inline(__always):重视使用内敛优化。函数很小且希望提高效率时使用(其实编译器也会做相应的优化,所以这样声明也不会提高速度)。

3.总结

struct / Enum Class NSObject Subclass
只要有final - Static Static
Extension Static Static Static
Extension + @objc / dynamic Static Static msgSend
默认 Static Table Table
@objc - Table Table
@objc dynamic - msgSend msgSend
Protocol Static Table Table

Reference:
Understanding Swift Performance
Optimizing Swift Performance
Swift 中的方法调用(Method Dispatch)(一) - 概述
Swift方法调用
Swift方法调用文章来源地址https://www.toymoban.com/news/detail-445936.html

到了这里,关于iOS_Swift函数派发机制的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 基于VS编译器探测成员函数指针的调用规则,并分析MFC消息映射实现机制的局限性问题

    /* 当想继承MFC的窗口类时,如果有多重继承,则继承的窗口类顺序要特别注意(要在继承列表的首个); 否则根据MFC消息映射机制的实现方式;调用指向成员函数指针时;根据前面的规则会触发代码混淆,导致运行期错误;如下: 这个也是MFC 窗体类继承顺序的问题的根本原因

    2024年02月06日
    浏览(25)
  • IOS-闭包学习-Swift

    闭包是自包含的函数代码块,可以在代码中被传递和使用。Swift 中的闭包与 C 和 Objective-C 中的代码块(blocks)以及其他一些编程语言中的匿名函数(Lambdas)比较相似。 闭包可以捕获和存储其所在上下文中任意常量和变量的引用。被称为包裹常量和变量。 Swift 会为你管理在捕

    2024年01月24日
    浏览(36)
  • iOS开发Swift-枚举

    枚举:一组相关的值定义了一个共同的类型,使你可以在代码中以类型安全的方式来使用这些值。 原始值:定义枚举时被预先填充的值。 (1)整数为原始值时,隐式赋值递增1。未设置原始值时,默认为0,之后递增1. (2)字符串为原始值,隐式赋值为枚举成员的名称。

    2024年02月11日
    浏览(36)
  • iOS开发Swift-闭包

    将很长的闭包表达式作为最后一个参数传递给函数,不用写出他的参数标签。 嵌套函数可捕获其外部函数所有参数、变量、常量。 当一个闭包作为一个参数传到一个函数中,但闭包在函数返回之后才被执行,则称闭包逃逸。 标注@escaping,表示允许闭包逃逸。  包装传递给函数

    2024年02月11日
    浏览(39)
  • IOS-生命周期-Swift

    App主要有五种状态,分别是: 未运行——Not running 应用程序没启动 未激活——Inactive 程序在前台运行,不过没有接收到事件。 一般每当应用要从一个状态切换到另一个不同的状态时,中途过渡会短暂停留在此状态。唯一在此状态停留时间比较长的情况是:当用户锁屏时,或

    2024年01月23日
    浏览(44)
  • iOS开发Swift-集合类型

    集合基本类型:数组 Array (有序), 集合 Set (无序不重复), 字典 Dictionary (无序键值对) (1)数组的表示 (2)创建空数组 (3)带值数组 (4)两数组相加创建数组 (5)字面量创造数组 (6)访问数组 (7)添加 (8)修改 (9)删除 (10)遍历 同时需要索引和值时: (1)集合的表示 (2)构造一个集合 (3)字面

    2024年02月11日
    浏览(38)
  • iOS开发Swift-基础部分

    系统可通过赋初始值进行自动推断。 平时可加可不加,同一行中有两句话必须加。 Int           UInt(最好不用) Double 64位 很大/高精度情况下使用 15位小数 Float 32位 对精度要求不高的情况下用 6位小数 十进制数   17 二进制 0b前缀 0b10001 八进制 0o前缀 0o21 十六进制 0x前缀

    2024年02月11日
    浏览(39)
  • iOS开发Swift-控制流

    (1)复合匹配 (2)区间匹配 (3)元组匹配 (4)值绑定匹配 (5)where continue, break, fallthrough, return, throw continue: 停止本次循环,开始下次循环 break: 立即结束整个控制流。可以使用break忽略switch的分支。 fallthrough贯穿: switch中的case加入贯穿,case会穿透到下一个case/ default。

    2024年02月11日
    浏览(40)
  • iOS开发系列--Swift语言

    Swift是苹果2014年推出的全新的编程语言,它继承了C语言、ObjC的特性,且克服了C语言的兼容性问题。Swift发展过程中不仅保留了ObjC很多语法特性,它也借鉴了多种现代化语言的特点,在其中你可以看到C#、Java、Javascript、Python等多种语言的影子。同时在2015年的WWDC上苹果还宣布

    2024年02月06日
    浏览(38)
  • iOS开发Swift-类型转换

    1.Int或Double转字符串 2.Double转Int(去掉小数点后面的) 3.Int转Double 4.向上转型 5.向下转型

    2024年02月09日
    浏览(29)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包