Runtime原理及应用

一、iOS Runtime原理及应用

Objc是一门动态语言,总是想办法把一些决定工作从编译推迟到运行时。也就是说只有编译器不够的,还需要一个运行时系统(Runtime system)来执行编译后的代码。这就是Objective-C Runtime系统存在的意义,它是整个Objc运行框架的基石。iOS的sdk中usr/include/objc文件夹下面有这个几个文件

Runtime原理及应用_第1张图片

都是和运行时相关的头文件,其中主要使用的函数定义在message.h和runtime.h两个文件中。在message.h中主要包含了一些向对象发送消息的函数,这是OC对象方法调用的底层实现。使用时需要导入头文件:

runtime.h是运行时最重要的文件,其中包含了对运行时操作的方法(导入头文件#import点击进去就可以看到):操作对象的类型定义:

这些类型的定义,对一个类进行了完全的分解,将类定义或者对象的每一个部分都出想为一个类型type,对操作一个类属性和方法非常方便。OBJC2_UNAVAILABLE标记的属性是Object-C2.0不支持的,但实际上可以用相应的函数获取这些属性,例如:如果想要获取Class的name属性,可以按照如下方法获取:

函数的定义:

* 对对象进行操作的方法一般是以object_开头

* 对类进行操作的方法一般是以class_开头

* 对类或者对象的方法进行操作的方法一般以method_开头* 对成员变量进行操作的方法一般以ivar_开头

* 对属性进行操作的方法一般以property_开头

* 对协议进行操作的方法一般以protocol_开头

* 根据以上函数的前缀可以大致了解到层级关系。

二、runtime的应用

1)发送消息

方法调用的本质,就是让对象发送消息。

objc_msgSend,只有对象才能发送消息,营私以objc_开头。

使用消息机制前提,必须导入#import

消息机制简单使用:

我们可以通过clang来查看代码生成的CPP代码(后续还有相关文章讲解clang的使用方法)

最终代码,需要把当前代码重新编译,用xcide编译器,clang - rewrite-objc main.m

2)交换方法

交换方法实现的需求场景:自己创建了一个功能性的方法,在项目中多次被引用,当项目的需求发生改变时,要使用另一种功能代替这个功能,要求是不改变旧项目(也就是不改变原来方法的实现)

可以再累的分类中,再写一个新的方法(是符合新的需求的),然后交换两个方法的实现。这样,再不改变项目的代码,而只是增加了新的代码的情况下,就完成了项目的改进。

交换两个方法的实现一般写在类的load方法里面,因为load方法会在程序运行前家在一次,而initialize方法会在类或者子类在第一次使用的时候调用,当有分类的时候会调用多次。

Runtime原理及应用_第2张图片

3)类/对象的关联

关联对象不是为类/对象添加属性或者成员变量(因为在设置关联后也无法通过ivarList或者propertyList取得),而是为类添加一个相关的对象,通常用于存储类信息,例如存储类的属性列表数组,为将来字典转模型的方便。

使用方式一:不能给分类添加属性,以下使用方法是错误的。

使用方式二:给对象添加关联对象。(这个是正确的)

比如alertView一般传值,使用的是alertVIew的tag属性。我们想把更多的参数传给alertView代理:

Runtime原理及应用_第3张图片


objc_setAssociatedObject方法的参数解释:

1. 第一个参数id object, 当前对象

2. 第二个参数const void *key, 关联的key,是c字符串

3. 第三个参数id value, 被关联的对象的值

4. 第四个参数objc_AssociationPolicy policy关联引用的规则

4)动态添加方法

开发使用场景:如果一个类方法非常多,加载类到内存的时候也比较耗费资源,需要给每个方法生成映射表,可以使用动态给某个类,添加方法解决。

经典面试题:有没有使用performSelector,其实主要想问你有没有动态添加过方法。

5)字典转模型KVC实现

KVC:把字典中所有值给模型的属性赋值。这个是要求字典中的Key,必须要在模型里能找到相应的值,如果找不到就会报错。基本原理如:

但是,在实际开发中,从字典中取值,不一定要全部取出来。因此,我们可以通过重写KVC 中的 forUndefinedKey这个方法,就不会进行报错处理。

另外,我们可以通过runtime的方式去实现。我们把KVC的原理倒过来,通过遍历模型的值,从字典中取值。


基本的代码就是上面这样。

三、面试问题

1.说说什么是runtime

1>OC 是一个全动态语言,OC 的一切都是基于 Runtime 实现的

平时编写的OC代码, 在程序运行过程中, 其实最终都是转成了runtime的C语言代码, runtime算是OC的幕后工作者

比如:

OC :

[[Person alloc] init]

runtime :

objc_msgSend(objc_msgSend("Person" , "alloc"), "init")

2>runtime是一套比较底层的纯C语言API, 属于1个C语言库, 包含了很多底层的C语言API

3>runtimeAPI的实现是用 C++ 开发的(源码中的实现文件都是mm),是一套苹果开源的框架

2.使用过runtime吗,用它来做什么

发送消息、交换方法、类/对象的关联对象、动态添加方法、字典转模型KVC实现

你可能感兴趣的:(Runtime原理及应用)