使用runtime完成解档归档
简单的创建一个Person对象,并声明几个属性
@interface Person : NSObject<NSCoding> // 归档问题 必须遵守该协议 /** */ @property(copy,nonatomic)NSString * name; /** */ @property(assign,nonatomic)int age; @property(assign,nonatomic)int age1; @end
设置哪些属性是需要归档的
//告诉系统,归档哪些属性 - (void)encodeWithCoder:(NSCoder *)coder { //利用runtime 来归档!! unsigned int count = 0; // 拷贝一个类 的属性列表 Ivar * ivars = class_copyIvarList([Person class], &count); // 在C语言中 但凡看到了一个传递了基本数据类型的指针 一般都是在函数中 改变外面参数的值 (这个ivars 可以形象的比喻为 数组 但是又区别于数组 如当我们 做ivars[100] 有可能不会报我们常见的数组越界而返回一个null 所以你懂得) for (int i = 0; i < count; i++) { //拿出每一个Ivar Ivar ivar = ivars[i]; const char * name = ivar_getName(ivar); // 将属性转行成字符串 NSString * KEY = [NSString stringWithUTF8String:name]; //归档 [coder encodeObject:[self valueForKey:KEY] forKey:KEY]; // 通过KVC 来拿到当前类 的属性 } //C语言里面!! 一旦遇到了copy creat new 需要释放 (否则 我们归档一次 内存泄漏一次 导致内存暴增) free(ivars); }
设置哪些属性需要解档
- (instancetype)initWithCoder:(NSCoder *)coder { self = [super init]; if (self) { unsigned int count = 0; Ivar * ivars = class_copyIvarList([Person class], &count); for (int i = 0; i < count; i++) { Ivar ivar = ivars[i]; const char * name = ivar_getName(ivar); NSString * KEY = [NSString stringWithUTF8String:name]; //解档 id value = [coder decodeObjectForKey:KEY]; //通过KVC 设置 [self setValue:value forKey:KEY]; // 通过KVC 将拿到的 值 设置给当前类 的 属性 } free(ivars); // 释放内存 } return self; }
使用
- (IBAction)save:(id)sender { //创建一个对象 Person * p = [[Person alloc]init]; p.name = @"hank"; p.age = 18; p.age1 = 18; NSString * tmpPath = NSTemporaryDirectory(); // 这里我们暂且放在 temp 路径里 NSString * filePath = [tmpPath stringByAppendingPathComponent:@"hank.hank"]; //归档!! [NSKeyedArchiver archiveRootObject:p toFile:filePath]; } - (IBAction)read:(id)sender { //路径 NSString * tmpPath = NSTemporaryDirectory(); NSString * filePath = [tmpPath stringByAppendingPathComponent:@"hank.hank"]; //解档 Person * p = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath]; NSLog(@"%@老师今年%d岁了!真实年龄是:%d",p.name,p.age,p.age1); }
优点:但当该类拥有上百个属性时,那将会花费更多的功夫在重复代码上,所以使用运行时机制截取类的成员变量,进行赋值,节省了大量的开发时间
by:ml