1.对runtime的理解
- runtime是系统在运行的时候的一些机制,其中最主要的是消息机制。
- OC从三种不同的层级上与runtime进行交互,分别是通过OC源码,通过Foundation框架的NSObject类定义的方法,通过对runtime函数的直接调用。大部分情下runtime自动在幕后工作。
- 对于C语言,函数的调用在编译的时候会决定调用哪个函数,编译完成之后直接顺序执行,无任何二义性。
- OC的函数调用成为消息发送。属于动态调用过程。在编译的时候并不能决定真正调用哪个函数(事实证明,在编译阶段,OC可以调用任何函数,即使这个函数并未实现,只要申明过就不会报错。而C语言在编译阶段就会报错)。
2. runtime的使用
- 1.将某些OC代码转为运行时代码,探究底层。
- 2.拦截系统自带的方法调用,也可以说成对系统的方法进行替换,比如拦截imageNamed:、viewDidLoad、alloc;例如:
- a、为UIImage建一个分类(UIImage+Category),实现一个自定义方法
+ (UIImage *)customImageNamed:(NSString *)name {
doubleversion = [[UIDevicecurrentDevice].systemVersiondoubleValue];
if(version >=8.0) {
// 如果系统版本是8.0以上,使用另外一套文件名结尾是‘_os7’的扁平化图片
name = [name stringByAppendingString:@"_os7"];
}
return[UIImagecustomNamed:name];
}
- b、分类中重写UIImage的load方法,实现方法的交换
+ (void) load {
// 获取两个类的类方法
Method m1 = class_getClassMethod([UIImageClass],@selector(imageNamed:));
Method m2 = class_getClassMethod([UIImageClass],@selector(customImageNamed:));
method_exchangeImplementations(m1, m2);
}
>注意:自定义方法中最后一定要再调用一下系统的方法,让其有加载图片的功能,但是由于方法交换,系统的方法名已经变成了我们自定义的方法名(有点绕,就是用我们的名字能调用系统的方法,用系统的名字能调用我们的方法),这就实现了系统方法的拦截!
- 3.实现分类也可以增加属性。
- 4.实现NSCoding的自动归档和自动解档;(不用对每个属性edcode和decode了,使用运行时可以遍历出每个对象的属性,数组的方式遍历eccode,decode)
- 用运行时的归档方法
- (void) encodeWithCoder: (NSCoder *) encoder {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count);
for (int i = 0; i < count; i++) {
// 取出i位置对应的成员变量
Ivar ivar = ivars[i];
// 查看成员变量
const char *name = ivar_getName(ivar);
// 归档
NSString *key = [NSString stringWithUTF8String:name];
id value = [self valueForKey:key];
[encoder encodeObject: value forKey:key];
}
free(ivars);
}
- 用运行时的解归档方法
- (id) initWithCoder: (NSCoder *) decoder {
if (self = [super init]) {
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([Person class], &count);
for (int i = 0; i < count; i++) {
// 取出i位置对应的成员变量
Ivar ivar = ivars[i];
// 查看成员变量
const char *name = ivar_getName(ivar);
// 归档
NSString *key = [NSString stringWithUTF8String:name];
id value = [self valueForKey:key];
[encoder encodeObject: value forKey:key];
}
free(ivars);
}
return self;
}
- 5.实现字典和模型的自动转换(核心就是可以遍历出字典中的每个属性,json解析中大牛框架都用了这个特性,包括MJEXtension,YYModel,jsonModel都是将json转换为字典,再遍历字典中的每个属性来进行modle的转换)。
- 经查看源码发现获取属性的列表的方法是字典转模型的比较核心方法:
OBJC_EXPORT Ivar *class_copyIvarList(Class cos, unsigned int *outCount)
__OSX_AVAILABLE_STARTING(__MAC_10_5,__IPHONE_2_0);
结论: 使用运行时动态获取属性的属性名的方法,来进行字典转模型替换,字典转模型效率最高的(耗时最短的)的是KVC,其他的字典转模型是在KVC 的key 和Value 做处理,动态的获取json 中的key 和value
- 经查看源码发现获取属性的列表的方法是字典转模型的比较核心方法: