runtime 实现 归档和解档
runtime 是一套比较底层的纯 C 语言 API, 平时写的 OC 代码都会转成 runtime 的 C 语言代码.
利用 runtime 可以动态的创建类(例如KVO的底层实现), 动态的创建修改方法和属性.
在自定义归档解档的时候 (NSCoding 技术), 当对象中的成员属性太多的时候, 需要写很多大部分重复的代码, 如果用 runtime 来动态的遍历对象的所有属性, 可以很方便的简化代码. 下面用一个 Demo 进行演示:
首先 runtime 常用的头文件有
// 遍历对象的所有属性
class_copyIvarList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>)
//遍历对象的所有方法
class_copyMethodList(<#__unsafe_unretained Class cls#>, <#unsigned int *outCount#>)
runtime 结合 KVC 实现归档和解档操作:
#import <objc/runtime.h>
#import <objc/message.h>
@implementation Person
// 归档
- (void)encodeWithCoder:(NSCoder *)coder{
// 计算对象成员变量的个数
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i=0; i<count; ++i) {
// 取出i位置对应的成员变量
Ivar ivar = ivars[i];
// 查看成员变量
const char *ivarName = ivar_getName(ivar);
// 生成 key
NSString *key = [NSString stringWithFormat:@"%s", ivarName];
// KVC 按 key 取值
id value = [self valueForKey:key];
//归档
[coder encodeObject:value forKey:key];
}
// 释放 ivars 指针
free(ivars);
}
// 解档
- (instancetype)initWithCoder:(NSCoder *)decoder{
if (self = [super init]) {
// 计算对象成员变量的个数
unsigned int count = 0;
Ivar *ivars = class_copyIvarList([self class], &count);
for (int i=0; i<count; ++i) {
// 取出i位置对应的成员变量
Ivar ivar = ivars[i];
// 查看成员变量
const char *ivarName = ivar_getName(ivar);
// 生成 key
NSString *key = [NSString stringWithFormat:@"%s", ivarName];
// 解档
[self setValue:[decoder decodeObjectForKey:key] forKey:key];
}
// 释放 ivars 指针
free(ivars);
}
return self;
}
@end
// main 函数:
Person *person = [[Person alloc] init];
person.name = @"小明";
person.age = 20;
person.height = 175.0;
//存储路径
NSString *documentPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject];
//NSLog(@"%@", documentPath);
//归档
NSString *filePath = [documentPath stringByAppendingPathComponent:@"person.dat"];
[NSKeyedArchiver archiveRootObject:person toFile:filePath];
//解档
Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
NSLog(@"%@--%d--%f", p.name, p.age, p.height);
不积跬步,无以至千里;不积小流,无以成江海。