Runtime简称运行时,就是系统在运行时一些机制,其中最主要的是消息机制。 Runtime基本是用C和汇编写的,从而有了动态系统的高效。
C语言:
- 函数的调用在编译的时候就决定调用哪个函数,编译完成之后直接顺序执行,无任何二义性。
- C语言在编译阶段调用未实现的函数就会报错
Objective-C:
函数的调用成为消息发送objc_msgSend,属于动态调用过程。 在编译时不能决定调用哪个函数(事实证明,在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要声明过就不会报错) Objective-C从三种不同的层级上与Runtime系统进行交互,分别是:
- 通过 Objective-C 源代码
- 通过 Foundation 框架的NSObject类定义的方法
- 通过对 runtime 函数的直接调用
通过 Objective-C 源代码。
多数情况我们只需要编写Objective-C代码即可,Runtime系统自动在幕后搞定一切,编译器会将 OC 代码转换成运行时代码,在运行时确定数据结构和函数。
通过 Foundation 框架的NSObject类定义的方法。
在cocoa程序中绝大部分类都是 NSObject 类的子类,所以都继承了 NSObject 的行为,而在 NSObject 类中仅仅定义了完成部分事情的模板,但没有提供所需要的代码。例如 -description
方法,该方法返回类内容的字符串,主要用来调试程序。
在NSObject类中,提供了以下方法可以从 Runtime 系统中获取信息:
-class
方法返回对象的类;
-isKindOfClass:
和 -isMemberOfClass:
方法检查对象是否存在于指定的类的继承体系中(是否是其子类或者父类或者当前类的成员变量);
-respondsToSelector:
检查对象能否响应指定的消息;
-conformsToProtocol:
检查对象是否实现了指定协议类的方法;
-methodForSelector:
返回指定方法实现的地址。
通过对 runtime 函数的直接调用
获取指定类
代码语言:javascript复制Class exampleClass = object_getClass([Example class]);
自定义selector方法
代码语言:javascript复制SEL testSEL = @selector(customSelector);
获取类方法
代码语言:javascript复制Method testMethod = Method class_getClassMethod(Class exampleClass , SEL testSEL);
获取实例方法
代码语言:javascript复制Method class_getInstanceMethod(Class exampleClass , SEL testSEL)
添加方法
代码语言:javascript复制BOOL addSucc = class_addMethod(exampleClass, testSEL, method_getImplementation(newMethod), method_getTypeEncoding(newMethod));
替换方法
代码语言:javascript复制class_replaceMethod(exampleClass, cusSEL, method_getImplementation(oriMethod), method_getTypeEncoding(oriMethod));
交叉互换方法
代码语言:javascript复制method_exchangeImplementations(oriMethod, newMethod);
获取一个类的属性列表,返回数组格式
代码语言:javascript复制objc_property_t *propertyList = class_copyPropertyList([self class], &count);
获取一个类的方法列表
代码语言:javascript复制Method *methodList = class_copyMethodList([self class], &count);
获取一个类的成员变量列表
代码语言:javascript复制Ivar *ivarList = class_copyIvarList([self class], &count);
获取成员变量的名字
代码语言:javascript复制const char *ivar_getName(Ivar v)
获取成员变量的类型
代码语言:javascript复制const char *ivar_getTypeEndcoding(Ivar v)
获取一个类的协议列表,返回为数组
代码语言:javascript复制__unsafe_unretained Protocol **protocolList = class_copyProtocolList([self class], &count);
set方法
代码语言:javascript复制void objc_setAssociatedObject(id object , const void *key ,id value ,objc_AssociationPolicy policy)
//将值value 跟对象object 关联起来(将值value 存储到对象object 中)
//object参数表示指定对象设置属性
//key参数:一个属性对应一个key,将来可以通过key取出这个存储的值,key 可以是任何类型
//value参数:为属性设置的值
//policy参数:设置存储策略(assign、strong、weak等)
利用参数key 将对象object中存储的对应值取出来
代码语言:javascript复制id objc_getAssociatedObject(id object , const void *key)