Runtime又叫运行时,是一套底层的C语言API,其为iOS内部核心之一,我们平时编写的OC代码,底层都是基于它来实现的,比如:
[receiver message];
//底层运行时会被编译转化为:
objc_msgSend(receiver,selector)
//如果其还有参数,比如:
[receiver message:(id)arg...];
//底层运行时会被编译器转化为:
objc_msgSend(receiver,selector,arg,arg...)
为什么需要Runtime?
OC是一门动态语言,他会将一些工作放在代码运行时才处理而并非编译时。也就是说,有很多类和成员变量在我们编译的时是不知道的,而在运行时,我们所编写的代码会转换成完整的代码运行。
因此,编译器是不够的,我们需要一个运行时系统来处理编译后的代码。
Runtime基本是用C汇编写的,由此可见苹果为了动态系统的高效而做出努力。苹果和GNU各自维护一个开源的Runtime版本,这两个版本之间都在努力保持一致。
Runtime的作用:
OC在三种层面上与Runtime系统进行交互:
通过OC源代码:只需要编写OC代码,Runtime系统自动在幕后搞定一切,调用方法,编译器会将OC转换成运行时代码,在运行时确定数据结构和函数。
2.通过foundation框架的NSObject类定义的方法:Cocoa程序中绝大部分都是NSObject的子类,所以都继承了NSObject的行为。(NSProxy是一个例外,他是一个抽象超类)
一般情况下,NSObject类仅仅定义了完成某件事情的模板,并没有提供所需要的代码。例如:-description方法,该方法返回类内容的字符串表示,该方法主要用来调试程序。NSObjec类并不知道子类的内容,所以它只是返回类的名字和对象的地址,NSObjec的子类可以重新实现。
还有一些NSObjec的方法可以从Runtime系统中获取信息,允许对象进行自我检查。例如:
-class 方法返回对象的类;
-iskindofclass:和-ismemberofclass:方法检查对象是否存在于指定的类的继承体系中(是否是其子类或者父类或者当前类的成员变量);
-respondstoselector:检查对象能否影响指定的消息;
-conformstoprotocol:检查对象是否实现了指定协议类的方法;
-methodforselector:返回指定方法实现的地址。
3.通过Runtime库函数直接调用
Runtime系统是具有公开接口的动态共享库。头文件存放于/usr/include/objc目录下,这意味着我们使用时只需要引入 objc/Runtime.h即可。
许多函数可以让你使用纯C代码来实现objc中同样的功能。除非写一些objc与其他语言的桥接或是底层的debug工作,你在写objc代码时一般不会用到这些C语言函数