[关闭]
@kingw 2016-04-23T10:13:53.000000Z 字数 4182 阅读 1221

归档解档

归档 接档: ios数据持久化


归档就是说,将一个对象写入到文件中。
这里储存是经过编码的。打开归档文件,是读不懂的。
而plist是可读的。(明文)

简单的归档

使用NSKeyedArichiver进行归档、NSKeyedUnarchiver进行接档,这种方式会在写入、读出数据之前对数据进行序列化、反序列化操作。

归档

  1. NSString *homeDictionary = NSHomeDirectory();//获取根目录
  2. NSString *homePath = [homeDictionary stringByAppendingPathComponent:@"atany.archiver"];//添加储存的文件名
  3. BOOL flag = [NSKeyedArchiver archiveRootObject:@”归档” toFile:homePath];//归档一个字符串

这种方式可以对字符串、数字等进行归档,当然也可以对NSArray与NSDictionary进行归档。返回值Flag标志着是否归档成功,YES为成功,NO为失败。

接档:

  1. NSKeyedUnarchiver unarchiveObjectWithFile:homePath]

归档自定义对象

接下来,我们将一个Person对象进行归档,并且接归档。
1.新建Personlei类

Person.h

  1. #import <Foundation/Foundation.h>
  2. @interface Person : NSObject
  3. @property (nonatomic, copy) NSString *name;
  4. @property (nonatomic, assign) int age;
  5. @end

Person.m

  1. @implementation Person
  2. //解档方法
  3. - (instancetype)initWithCoder:(NSCoder *)coder
  4. {
  5. if (self=[super init]) {
  6. _name = [coder decodeObjectForKey:@"name"];
  7. _age = [coder decodeIntForKey:@"age"];
  8. }
  9. return self;
  10. }
  11. //归档方法
  12. - (void)encodeWithCoder:(NSCoder *)coder
  13. {
  14. // 成员变量_name按照name进行归档。接档时也必须是name进行解归档。同一个成员变量,归档和解档的key是一样的。
  15. [coder encodeObject:_name forKey:@"name"];
  16. [coder encodeInt:_age forKey:@"age"];
  17. }
  18. @end

2.操作归档
创建一个Person对象

  1. Person *p = [[Person alloc] init];
  2. p.name = @"abc";
  3. p.age = 100;

将这个Person对象进行归档

  1. #define PATH [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"account.data"]
  2. [NSKeyedArchiver archiveRootObject:p toFile:PATH];
  3. //BOOL flag = [NSKeyedArchiver archiveRootObject:@”归档” toFile:homePath];//归档一个字符串

将这个Person对象进行解解归档

  1. #define PATH [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"account.data"]
  2. // 返回bool值,yes表示成功。
  3. Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:PATH];

注意:以上文件名account.data后缀名可以随意写。但必须一样。是同一个文件。

这种归档的方式存在一个缺点:只能把一个对象归档进一个文件中,那么怎么对多个对象进行归档呢?

归档多个对象

同样是使用NSKeyedArchiver进行归档,不同的是同时归档多个对象,这里我们举例放入了一个CGPoint点、字符串、整数(当然很多类型都可以的,例如UIImage、float等等),使用encodeXXX方法进行归档,最后通过writeToFile方法写入文件。

  1. // 准备数据
  2. CGPoint point = CGPointMake(1.0, 2.0);
  3. NSString *info = @"坐标原点";
  4. NSInteger value = 10;
  5. // 文件储存路径
  6. NSString *multiHomePath = [NSHomeDirectory() stringByAppendingPathComponent:@"multi.archiver"];
  7. // 储存多个归档对象的数据
  8. NSMutableData *data = [[NSMutableData alloc]init];
  9. // 归档对象
  10. NSKeyedArchiver *archvier = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
  11. // 对多个对象进行归档
  12. [archvier encodeCGPoint:point forKey:@"kPoint"];
  13. [archvier encodeObject:info forKey:@"kInfo"];
  14. [archvier encodeInteger:value forKey:@"kValue"];
  15. [archvier finishEncoding];
  16. // 将data写入文件。
  17. [data writeToFile:multiHomePath atomically:YES];

接档:从路径中获得数据构造NSKeyedUnarchiver实例,使用decodeXXXForKey方法获得文件中的对象。

  1. NSMutableData *dataR = [[NSMutableData alloc]initWithContentsOfFile:multiHomePath];
  2. NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:dateR];
  3. CGPoint pointR = [unarchiver decodeCGPointForKey:@"kPoint"];
  4. NSString *infoR = [unarchiver decodeObjectForKey:@"kInfo"];
  5. NSInteger valueR = [unarchiver decodeIntegerForKey:@"kValue"];
  6. [unarchiver finishDecoding];
  7. NSLog(@"%f,%f,%@,%d",pointR.x,pointR.y,infoR,valueR);

新建归档接档的基础类,需要归档解当的类继承自它就可以

  1. #import "KKBaseCoder.h"
  2. #import <objc/runtime.h>
  3. @implementation KKBaseCoder
  4. //归档与解归档的方法
  5. - (instancetype)initWithCoder:(NSCoder *)coder
  6. {
  7. self = [super init];
  8. if (self) {
  9. //获取所有属性
  10. NSArray * porpertyArray = [self getAllPropertys];
  11. for (NSString * name in porpertyArray) {
  12. //去掉属性名前面的_
  13. NSString * key = [name substringFromIndex:1];
  14. //约定好的键值对 c+key
  15. [self setValue:[coder decodeObjectForKey:[NSString stringWithFormat:@"a%@",key]] forKey:key];
  16. }
  17. }
  18. return self;
  19. }
  20. - (void)encodeWithCoder:(NSCoder *)coder
  21. {
  22. //获取所有属性
  23. NSArray * porpertyArray = [self getAllPropertys];
  24. for (NSString * name in porpertyArray) {
  25. //去掉属性名前面的_
  26. NSString * key = [name substringFromIndex:1];
  27. //约定好的键值对 c+key
  28. [coder encodeObject:[self valueForKey:key] forKey:[NSString stringWithFormat:@"a%@",key]];
  29. }
  30. }
  31. //获取model所有属性
  32. - (NSArray *)getAllPropertys{
  33. NSMutableArray * array = [[NSMutableArray alloc]init];
  34. unsigned int * count = malloc(sizeof(unsigned int));
  35. //调用runtime的方法
  36. //Ivar:方法返回的对象内容对象,这里将返回一个Ivar类型的指针
  37. //class_copyIvarList方法可以捕获到类的所有变量,将变量的数量存在一个unsigned int的指针中
  38. Ivar * mem = class_copyIvarList([self class], count);
  39. //进行遍历
  40. for (int i=0; i< *count ; i++) {
  41. //通过移动指针进行遍历
  42. Ivar var = * (mem+i);
  43. //获取变量的名称
  44. const char * name = ivar_getName(var);
  45. NSString * str = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];
  46. [array addObject:str];
  47. }
  48. //释放内存
  49. free(count);
  50. //注意处理野指针
  51. count=nil;
  52. return array;
  53. }
  54. @end
添加新批注
在作者公开此批注前,只有你和作者可见。
回复批注