iOS 底层原理 iOS 进阶之路

OC底层原理十二: objc_msgSend(方法快速查找)

2020-09-19  本文已影响0人  markhetao

OC底层原理 学习大纲

上一节已了解类的cache结构插入操作。但是有几个问题:

cache分析流程

现在开始探索之旅

1. 探索插入操作
2. 介绍Runtime
3. 了解方法的本质
4. objc_msgSend解析

1. 探索插入操作

我们从insert开始寻找谁在调用它

image.png image.png

我们发现,在缓存写入之前,我们需要先知道:

到这里,我们必须引出OC非常重要的机制:Runtime运行时

2. 介绍Runtime

👉 Objective-C Runtime Programming Guide,此文档不再更新,适合初步了解Runtime

2.1 什么是Runtime

2.2 什么是运行时? 什么是编译时?

  • 编译过程中,会分析语法是否正确。
  • 编译时提示的errorwarning都是编译时错误
  • 编译过程检查就叫编译时类型检查静态类型检查
  • 代码在装载内存之前,只是个"死家伙",静静地趴在磁盘中。只有载入内存,才是"活的"
  • 运行时类型检查与前面所说的编译时类型检查(或叫静态类型检查)不一样,它不是简单的扫描代码,而是在内存中做些操作,做些判断。(是动态活动的)

例如一个函数,只声明未实现command+B编译时不会报错,但是command+R运行时会报错。

image.png

2.3 Runtime版本

  • 早期版本: Objective-C 1.0,用于32位Mac OS X的平台上,实例变量发生改变后,需要重新编译其子类
  • 现行版本: Objective-C 2.0,用于iPhone程序和Mac OS X v10.5以后的系统中的 64 位程序实例变量发生改变后,不需要重新编译其子类

2.4 运行时让OC具备多态特性

例如:
自然界中的人类(Person)都有一个相同的方法-sing,男人(Man)类属于人类,女人(Wonan)类也属于人类,都继承了人类后,会实现各自的-sing方法。但是自然界中男人和女人的sing风格又不一样,男人唱的豪迈女人唱的委婉,但都继承了person唱的能力,这就是多态的现象。
也就是不同的对象以自己的方式响应相同消息的能力叫多态。 也可以说运行时机制是多态基础
描述参考👉: 码上江湖

2.5 Runtime的三种调用

2.6 探索runtime

先准备好静态资源的,咱们才能动态起来。所以先获取compiler层文件。

@interface HTPerson : NSObject
- (void)sayHello;
@end

@implementation HTPerson
- (void)sayHello{
    NSLog(@"%s",__func__);
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {

        HTPerson *p  = [HTPerson alloc];
        [p sayHello];
    }
    return 0;
}
image.png

我们发现,所有OC方法,不管是类方法alloc,还是实例方法sayHello都是调用了objc_msgSend发送消息。

  1. 导入头文件#import <objc/message.h>
  2. 手动关闭运行时的编译警告: buildSetiing->Enable Strict Checking of objc_msgSend Calls->设置为No
  3. 加入测试代码objc_msgSend(p, sel_registerName("sayHello"));
  4. 打印查看:
image.png

崩溃暂时不理会,我们现在发现sayHello打印成功了

3. 了解方法的本质

我们知道,方法的本质就是一个方法名和对应的函数代码

  • 第一步: 发送消息我们有三种API调用方法(oc代码调用、framework调用 、RuntimeAPI调用)
  • 第三步:可直接 从函数指针地址读取函数内容

上述流程,我们唯一不知道的就是系统如何通过sel(方法编号)找到imp(函数指针地址)?

4. objc_msgSend解析

了解sel如何找到imp就是探究 objc_msgSend内部机制。

接下来的知识,需要大家先熟悉cache_t的结构

汇编查找函数的流程: 从指定类开始->定位cache->定位buckets->哈希运算获取首次位置->循环寻找位置->返回impnull

image.png image.png image.png image.png image.png

奉上完整流程

image.png

下一节: OC底层原理十三: objc_msgSend(方法慢速查找)

上一篇 下一篇

猜你喜欢

热点阅读