归档和反归档
复杂的对象我们并不能通过writeToFile类型的方法写入到文件中。 这里的复杂对象指的是在Foundation框架内部存在的数据类,这个负载对象至少包含有一个实例对象
如果想要进行归档和反归档操作,则必须遵守 <NSCoding>协议
我们在归档和解档操作时, 每一个需要一个键. 并且归档时是什么键, 那么解档时就需要用到什么键值, 我推荐大家使用宏定义, 这样的话不至于混淆.并且在写的时候最好见名知意.如图:
构建一个学生类, 包含姓名, 年龄, 性别三个属性, 声明初始化方法。并且宏定义键
接下来在.m文件中实现解档和归档的方法
归档我们使用方法:
- (void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:kStudentNameKey];
[aCoder encodeObject:self.sex forKey:kStudentSexKey];
[aCoder encodeInteger:self.age forKey:kStudentAgeKey];
}
在ViewController中创建学生两个对象
NSArray *students = @[stu1,stu2];//然后将学生对象存到数组中.
//然后我们获取存储数据的路径并指定存储格式
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsPath = paths.firstObject;
NSString *stuPath = [documentsPath stringByAppendingPathComponent:@"students.plist"];
调用NSKeyedArchiver方法进行归档操作
[NSKeyedArchiver archiveRootObject:students toFile:stuPath];
运行之后我们的数据就会存储在沙盒文件夹中.
如果需要取出数据的话, 就需要我们做反归档操作, 在student.m文件写出Student的反归档方法,注意键要和归档时一样~! 宏定义的优势瞬间就体现了出来
- (id)initWithCoder:(NSCoder *)aDecoder{
if (self = [super init]) {
self.name = [aDecoder decodeObjectForKey:kStudentNameKey];
self.sex = [aDecoder decodeObjectForKey:kStudentSexKey];
self.age = [aDecoder decodeIntegerForKey:kStudentAgeKey];
}
return self;
}
NSArray *unArcStus = [NSKeyedUnarchiver unarchiveObjectWithFile:stuPath];
打印一下数据, 看是否取出了归档时存入的数据for (Student *stu in unArcStus){
NSLog(@"%@, %@, %ld", stu.name, stu.sex, stu.age);
}
NSLog(@"%lu", stu1.name.retainCount);
可以看到利用反归档方式取出了存入的数据.
如果归档/反归档会出错, 我总结道德常见错误有:
1. 野指针/内存泄露(哪儿里都常见,如果用MRC环境的话, 注意引用计数的平衡)
2. 键值不统一(用宏定义基本不会存在)
3. 错误的路径