runtime就是运行时机制,可以通过命令行clang -rewrite-objc 对应的目标文件,就能将对应的OC的代码转成对应的运行时的代码
所有的OC类和对象,在runtime层都是用struct表示的.
用处:
- 1、在category中想添加属性,则可与使用runtime动态添加。
objc_setAssociatedObject(self, @selector(summaryDataModel), summaryDataModel, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_getAssociatedObject(self, _cmd);
ex:实现属性的set、get方法
@property (nonatomic, strong) NSString *title;
- (NSString *)title {
return objc_getAssociatedObject(self, _cmd);
}
- (void)setTitle:(NSString *)title {
objc_setAssociatedObject(self, @selector(title), title, OBJC_ASSOCIATION_RETAIN);
}
- 2、KVO 是基于运行时实现的 isa Class NSKVONotifying_Person
Apple 使用了 isa 混写(isa-swizzling)来实现 KVO。当观察对象A时,KVO机制动态创建一个新的名为:NSKVONotifying_A 的新类,该类继承自对象A的本类,且 KVO 为 NSKVONotifying_A 重写观察属性的 setter 方法,setter 方法会负责在调用原 setter 方法之前和之后,通知所有观察对象属性值的更改情况。
isa:is a kind of.isa指针指向类对象. - 3、Method Swizzling:方法交换 运用Runtime,在加载时将方法进行调换,来统计数据或者修复bug。 一般在类方法load里面进行。
附:class声明:
#import <objc/runtime.h>
struct objc_class {
Class _Nonnull isa OBJC_ISA_AVAILABILITY;
#if !__OBJC2__
Class _Nullable super_class OBJC2_UNAVAILABLE;
const char * _Nonnull name OBJC2_UNAVAILABLE;
long version OBJC2_UNAVAILABLE;
long info OBJC2_UNAVAILABLE;
long instance_size OBJC2_UNAVAILABLE;
struct objc_ivar_list * _Nullable ivars OBJC2_UNAVAILABLE;
struct objc_method_list * _Nullable * _Nullable methodLists OBJC2_UNAVAILABLE;
struct objc_cache * _Nonnull cache OBJC2_UNAVAILABLE;
struct objc_protocol_list * _Nullable protocols OBJC2_UNAVAILABLE;
#endif
} OBJC2_UNAVAILABLE;
7、runtime流程:
一个对象的方法像这样[obj foo],编译器转成消息发送objc_msgSend(obj, foo),Runtime时执行的流程是这样的.
Runtime时执行的流程是这样的:
首先,通过obj的isa指针找到它的 class ;
在 class 的 method list 找 foo ;
如果 class 中没到 foo,继续往它的 superclass 中找 ;
一旦找到 foo 这个函数,就去执行它的实现IMP 。
再找到foo 之后,把foo 的method_name 作为key ,method_imp作为value 给存起来。当再次收到foo 消息的时候,可以直接在cache 里找到,避免去遍历objc_method_list。
13、OC运行时语言
- 动态类型识别(Dynamic typing):最终判定该类的实例类型是在运行期间。
OC中有一个可以表示任何实例对象类型的关键字–id,将对象声明为id类型,可根据需要,赋予不同类型的实例对象。 - 动态绑定(Dynamic binding):在运行时确定调用的方法
- 动态加载(Dynamic loading):在运行期间可添加模块(类、方法),如方法交换,动态绑定属性等