Runtime详解

最近在研究Runtime,因此,打算写一篇文章跟小伙伴儿们分享一下。好了,废话不多说,直接上干货。

RunTime简称运行时。OC就是运行时机制,也就是在运行时候的一些机制,其中最主要的是消息机制。简单说一下C与OC在编译和运行阶段的区别,对于C语言,函数的调用在编译的时候会决定调用哪个函数。对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称找到对应的函数来调用。

Runtime有5大作用:发送消息,交换方法,动态添加方法,给分类添加属性,字典转模型,下面一一给大家讲解一下这5个作用。


一、发送消息

任何方法调用的本质就是发送一个消息,用runtime发送消息,OC底层就是通过runtime实现的。下面给大家展示一下底层的代码:

Runtime详解_第1张图片

正常的OC代码通过Xcode的编译器Clang重新编译,就会生成底层的代码,也就是消息机制的代码。话说回来,怎么使用编译器重新编译呢?我们在终端输入clang -rewrite-objc main.m 就可以得到最终生成代码了。

我们使用Runtime时,必须要提前导入头文件,可能有人会问我,为什么不导入?因为我们进入message.h的声明中,会发现已经导入了runtime.h。

上面展示的代码是最底层的代码,写着太麻烦了,很少用,下面给大家展示一下我们平常写的代码:

这个就是我们平常写的,第一个参数的意思是:谁发送消息       第二个参数的意思是:发送什么消息。

其实,还有一种写法,也是可以的:

上面仅仅给大家展示了一些消息机制底层代码的一下写法,下面说一下Runtime在消息机制中最重要的一个作用:“runtime消息机制,可以调用私有方法”!!!!!!

下面给大家展示一下,调用私有方法:


Runtime详解_第2张图片

上面的eat,run方法在Person类中均没有声明,只有实现。

注:我们在用对象p调用方法时,不要用Person *p = objc_msgSend(object_getClass(@"Person"), sel_registerName("alloc"))这种形式,否则,会崩。

上面是对象方法,下面给大家展示一下类方法。

对象方法的对象调用,类方法的本质是类对象调用。


Runtime详解_第3张图片

下面,给大家分享一下方法的调用流程:

1.去寻找对应的类对象,每一个对象都有一个isa指针,通过isa指针去对应类中查找;

2.注册方法编号

3.根据方法编号查找对应的方法

4.找到只是最终函数实现地址,根据地址去方法区调用对应函数。



二、交换方法

交换方法是Runtime中最常用的,我们在做项目时经常用到。

Runtime(交换方法):只要想修改系统的方法实现。

比如:有一个项目,已经开发了2年,忽然项目负责人添加一个功能,每次UIImage加载图片,告诉我是否加载成功?

这样的一个需求,除了使用Runtime交换方法,用其他的方法很难实现。

交换方法的步骤为:(1)给系统的方法添加分类;

                                (2)自己实现一个带有扩展功能的方法;

                                (3)交换方法的实现,只需要交换一次。

下面直接上代码:

分类的声明:

Runtime详解_第4张图片

分类的实现:

Runtime详解_第5张图片


Runtime详解_第6张图片


三、动态添加方法

动态添加方法:OC是懒加载机制,只要一个方法实现了,就会马上添加到方法列表中(不管这个方法有没有用过,都会添加进去)。如果某个类中方法比较多,而且有很多方法不常用,需要给每个方法都生成映射表,加载类到内存的时候就比较耗费资源,可以使用动态给该类添加方法解决。

下面直接上代码:

Person类的实现部分:

Runtime详解_第7张图片
Runtime详解_第8张图片

动态添加方法在做项目时用得比较少。


4、动态添加属性

我们给系统的类添加属性的时候,可以使用runtime动态添加属性。动态添加属性的本质:让某个属性和某个对象产生一个关联,并不是直接把这个值的内存空间添加到类内存空间。

代码如下:

Runtime详解_第9张图片

给系统的类添加一个分类,声明部分:


Runtime详解_第10张图片

实现部分:


Runtime详解_第11张图片



4、字典转模型

字典转模型有两种方法:1.KVC  2.Runtime。第三方框架MJExtension底层就是用Runtime字典转模型的。

KVC的实现原理是:遍历字典中所有的key,去模型中查找对应的属性赋值;Runtime实现原理刚好与KVC相反:通过runtime,把一个模型中所有属性遍历出来,根据属性去字典里面找。

我们可以创建一个NSObject分类,专门字典转模型,以后所有模型都可以通过这个分类转

代码如下:


Runtime详解_第12张图片

你可能感兴趣的:(Runtime详解)