之前很少使用Runtime,现在Runtime基本就是面试必问的问题了,Runtime是想要做好iOS开发,或者说是真正的深刻的掌握OC这门语言所必需理解的东西,现在就开始重新学习和总结一下Runtime。
一、什么是Runtime
- 我们写的代码在程序运行过程中都会被转化成runtime的C代码执行,例如
[target doSomething];
会被转化成objc_msgSend(target, @selector(doSomething));
。 - OC中一切都被设计成了对象,我们都知道一个类被初始化成一个实例,这个实例是一个对象。实际上一个类本质上也是一个对象,在runtime中用结构体表示。
RunTime简称运行时。OC就是运行时机制,也就是在运行时候 的一些机制,其中最主要的是消息机制。
对于C语言,函数的调用在编译的时候会决定调用哪个函数。
对于OC的函数,属于动态调用过程,在编译的时候并不能决定真正调用哪个函数,只有在真正运行的时候才会根据函数的名称
找到对应的函数来调用。
事实证明:
在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错。
在编译阶段,C语言调用未实现的函数就会报错。
Objective-C语言是一门动态语言,它将很多静态语言在编译和链接时期做的事放到了运行时来处理。
对于Objective-C来说,这个运行时系统就像一个操作系统一样:它让所有的工作可以正常的运行。Runtime基本上是用C和汇编写的,这个库使得C语言有了面向对象的能力。
在Runtime中,对象可以用C语言中的结构体表示,而方法可以用C函数来实现,另外再加上了一些额外的特性。这些结构体和函数被runtime函数封装后,让OC的面向对象编程变为可能。
找出方法的最终执行代码:当程序执行[object doSomething]时,会向消息接收者(object)发送一条消息(doSomething),runtime会根据消息接收者是否能响应该消息而做出不同的反应。
二、Runtime相关的头文件
ios的sdk中 usr/include/objc文件夹下面有上边这几个文件,主要使用的函数定义在message.h和runtime.h这两个文件中。
使用时,需要导入文件,导入如:
#import <objc/message.h> #import <objc/runtime.h>
操作对象的类型的定义
/// An opaque type that represents a method in a class definition. 一个类型,代表着类定义中的一个方法 typedef struct objc_method *Method; /// An opaque type that represents an instance variable.代表实例(对象)的变量 typedef struct objc_ivar *Ivar; /// An opaque type that represents a category.代表一个分类 typedef struct objc_category *Category; /// An opaque type that represents an Objective-C declared property.代表OC声明的属性 typedef struct objc_property *objc_property_t; // Class代表一个类,它在objc.h中这样定义的 typedef struct objc_class *Class; struct objc_class { Class isa OBJC_ISA_AVAILABILITY; #if !__OBJC2__ Class super_class OBJC2_UNAVAILABLE; const char *name OBJC2_UNAVAILABLE; long version OBJC2_UNAVAILABLE; long info OBJC2_UNAVAILABLE; long instance_size OBJC2_UNAVAILABLE; struct objc_ivar_list *ivars OBJC2_UNAVAILABLE; struct objc_method_list **methodLists OBJC2_UNAVAILABLE; struct objc_cache *cache OBJC2_UNAVAILABLE; struct objc_protocol_list *protocols OBJC2_UNAVAILABLE; #endif } OBJC2_UNAVAILABLE;
这些类型的定义,对一个类进行了完全的分解,将类定义或者对象的每一个部分都抽象为一个类型type,对操作一个类属性和方法非常方便。OBJC2_UNAVAILABLE
标记的属性是Ojective-C 2.0不支持的,但实际上可以用响应的函数获取这些属性,例如:如果想要获取Class的name属性,可以按如下方法获取:
Class classPerson = Person.class; // printf("%s\n", classPerson->name); //用这种方法已经不能获取name了 因为OBJC2_UNAVAILABLE const char *cname = class_getName(classPerson); printf("%s", cname); // 输出:Person
函数的定义
- 对对象进行操作的方法一般以
object_
开头 - 对类进行操作的方法一般以
class_
开头 - 对类或对象的方法进行操作的方法一般以
method_
开头 - 对成员变量进行操作的方法一般以
ivar_
开头 - 对属性进行操作的方法一般以
property_开头
开头 - 对协议进行操作的方法一般以
protocol_
开头
根据以上的函数的前缀 可以大致了解到层级关系。
对于以objc_
开头的方法,则是runtime最终的管家,可以获取内存中类的加载信息,类的列表,关联对象和关联属性等操作。
例如:使用runtime对当前的应用中加载的类进行打印,别被吓一跳。