runtime&runloop

iOS面试--Runtime(动态运行时)

2020-02-26  本文已影响0人  唐师兄

前言

2020年已经注定了:新型冠状病毒肆虐,追了 15 年的偶像Kobe与世长辞,禽流感来袭等等。这是多灾多难的一年! 太多的坏事情坏消息消耗了人们太多的热情和信心,我们只能将一切寄予希望,即使是很空虚的希望;我们憧憬新型冠状病毒的离开,生活重归于好,我们期待时间能够治愈科比离世带给我们的痛苦,所有的这些坏事情坏消息仅仅是一个开始,它们还没有开足马力,由于惯性,还会横冲直撞一段时间和路程。 过苦日子的悲惨现实,已经支撑不起伟大、强大和辉煌的梦想。所以我们只能寄希望于未来,而为了我们的未来,所以还是要继续前行!!!
Dear thoughts are in my mind, and my soul it soars enchanted.

矫情之后,还是要回归正题。关于 Runtime 的面试,我们主要从下面几个问题出发。

Runtime

runtime 概述

runtime 我们主要是从以下八个模块去分析,数据结构、类对象与元类对象、消息传递、方法缓存、方法转发、Method-Swizzling、动态添加方法以及动态方法解析,如下图所示


runtime 数据结构

objc_object

objc_object 其实就是 id,每一个 objc_object 中均有一个 isa 指针

objc_object 数据结构
Class == objc_class
objc_class

isa 指向

cache_t

主要用于提高方法调用的速度或者消息传递的速度

class_data_bits_t

class_rw_t

class_rw_t 的数据结构
class_rw_t 原理解析

https://www.jianshu.com/p/585845127007

class_ro_t

class_ro_t 数据结构

method_t

函数四要素:函数的名称、函数的返回值、函数的参数、函数体


method_t 数据结构

如上图所示

\color{red}{types 是如何表述函数的返回值和参数?}

Type Encodings runtime 数据结构表

对象、类对象、元类对象

对象、类对象、元类对象之间的关系图

如上图所示,实例对象可以通过 isa 指针找到其类对象,而类对象可以通过 isa 指针找到他的元类对象;同时类对象可以通过 superclass 指针找到它的 Superclass 对象一直到 Rootclass,元类对象也是如此;类对象和元类对象因为继承自 NSObject, 所以他们中也有 isa 指针,对于每一个元类对象的 isa 指针都指向根元类对象;根元类对象的 superclass指针指向的是根类对象

消息传递

消息传递流程图

缓存查找

类对象查找(已排序的列表采用二分查找、未排序的使用一般遍历)
元类对象查找(父类逐级遍历)

消息转发流程

消息转发流程
https://www.jianshu.com/p/ba0e9942a082

Method Swizzling

动态添加一个方法?

当面试官问你@dynamic关键字的时候,如何回答?

runtime 实际面试问题

1. [obj foo] 和 objc_msgsend()函数之间有什么关系?
 objc_msgSend()是[obj foo]的具体实现。
 在runtime中,objc_msgSend()是一个c函数,[obj foo]会被翻译成这样的形式objc_msgSend(obj, foo)。
系统会先去obj的对应的类中找方法;
再进行缓存,找不到再去找方法列表;
再找父类,如此逐级向上传递;
最后再找不到就要转发。
2. runtime 如何通过Selector 找到对应的 IMP 地址的?(考察消息传递机制)
对于实例方法,每个实例的 isa 指针指向着对应类对象,
而每一个类对象中都一个对象方法列表。
对于类方法,每个类对象的 isa 指针都指向着对应的元对象,
而每一个元对象中都有一个类方法列表。
方法列表中记录着方法的名称,方法实现,以及参数类型,
其实 selector 本质就是方法名称,通过这个方法名称就可以在方法列表中找到对应的方法实现。
Selector、Method 和 IMP 的关系可以这样描述:在运行时分发消息,方法列表中的每一个实体都是一个方法(Method),
它的名字叫做选择器(SEL),对应着一种方法实现(IMP)。
3. 能否向编译后的类中添加实例变量?
4. 能否向运行时动态创建的类中添加实例变量?为什么?
上一篇下一篇

猜你喜欢

热点阅读