zl程序教程

您现在的位置是:首页 >  移动开发

当前栏目

iOS底层原理(二):运行时研究(一)

ios原理 运行 研究 底层
2023-06-13 09:17:38 时间

运行

Objective-C扩展了C语言,并加入了面向对象特性和Smalltalk式的消息传递机制。而这个扩展的核心是一个用C和编译语言写的Runtime库。它是Objective-C面向对象和动态机制的基石。

Objective-C是一个动态语言,这意味着它不仅需要一个编译器,也需要一个运行时系统来动态得创建类和对象,进行消息传递和转发。理解Objective-C的运行时机制可以帮我们更好的了解这个语言,适当的时候还能对语言进行扩展,从系统层面解决项目中的一些设计或技术问题。一句话:学好运行时间,iOS躺着走

Runtime其实有两个版本:“ modern”和“ legacy”。我们现在用的采用Objective-C 2.0的是现行(Modern)版的Runtime系统,只能运行在iOSmacOS 10.5之后的64位程序中。而较macOS老的32位程序仍采用Objective-C 1中的(早期)Legacy的版本Runtime系统- 。这两个版本最大的区别在于当你更改一个类的实例变量的布局时,在早期版本中你需要重新编译它的子类,而现行版就不需要。

Runtime基本是用C汇编写的,可见苹果为了动态系统的高效而作出的努力。你可以在这里下到苹果维护的开源代码。苹果和GNU各自维护一个开源的运行时 / GNUStep版本,这两个版本之间都在努力的保持一致。

平时的业务中主要是使用官方Api,解决我们框架性的需求。

高级编程语言想要成为可执行文件需要先编译为汇编语言再汇编为机器语言,机器语言也是计算机能够识别的唯一语言,但是OC并不能直接编译为汇编语言,要先而是转写为纯C语言再进行编译状语从句:汇编的操作,从OCC语言的过渡就是由运行时来实现的。然而使用我们OC进行面向对象开发,而C语言更多的是面向过程开发,这就需要将面向对象的类转变为面向过程的结构体。

好我们先来看看与运行交互的三种方式:

  • OC原生底层就是运行会会在后台执行比如方法的实质就是消息 对于大多数情况下,OC运行时系统自动的在后台运行。你只需编写和编译OC代码就能使用它。 当你编译包含OC类和方法的代码时,编译器创建用来实现语言动态特性的数据结构体和方法调用。数据结构获取类和类定义的信息和协议中定义的信息,包含了在“Objective-C编程语言”中对“定义类和协议”谈论的类和协议的对象,以及方法选择,实例变量模版,和其他葱源代码中提取出来的信息。运行时主要的一个功能是发送消息,正如在消息中的描述。它是由源代码的消息表达式调用的。
  • 通过调用NSObject的方法间接调用运行时

这里给大家解释一下:以上方法都是在运行时会编译成响应的方法:- (BOOL)respondsToSelector:(SEL)aSelector比如我们看编译会来到objc的这里

上面的两部跳动,都是给下面的方法做铺垫的,的下面方法也。runtime非常重要的方法,下面我们花点篇幅介绍一下

lookUpImpOrForward这个方法里面篇幅很长里面介绍了以下几点:

  • 如果缓存是YES,则从缓存中查找IMP。这里也就是说我们如果之前响应过的,在高速缓存存过,就不需要下面的操作了
  • 判断类是否已经被创建,如果没有被创建,则将类实例化
  • 第一次调用当前类的话,执行初始化的代码
  • 尝试获取这个类的缓存(这里很多小伙伴就会质疑,为什么还要取一次内存,要知道OC是动态语言,在我们执行这个获取imp的时候,外界在开锁,解锁的时候是可以访问的,动态操作
  • 如果没有从缓存中查找到,则从方法列表中获取方法
  • 如果还没有,就从父类缓存或者方法列表获取小鬼
  • 如果没有找到,则尝试动态方法解析
  • 如果没有IMP被发现,并且动态方法解析也没有处理,则进入消息转发阶段

还有里面关于runtimeLock运行时锁,加锁这里了read()对读取,其中runtimeLock的英文通过pthread_rwlock_t实现的,更加底层的,如果大家感兴趣锁可以参考这篇互斥锁-读写锁-条件锁

以上设计了消息,, 动态方法解析还有消息转发,我们在接下来的篇幅中还会更加深入研究。我们继续回来,第三种runtime交互

  • 直接调用runtime的API IPA的介绍篇幅,我们就放到下一篇。

研究学习,我是认真的!