@kingw
2016-04-23T10:13:53.000000Z
字数 4182
阅读 1241
归档 接档: ios数据持久化
归档就是说,将一个对象写入到文件中。
这里储存是经过编码的。打开归档文件,是读不懂的。
而plist是可读的。(明文)
使用NSKeyedArichiver进行归档、NSKeyedUnarchiver进行接档,这种方式会在写入、读出数据之前对数据进行序列化、反序列化操作。
归档
NSString *homeDictionary = NSHomeDirectory();//获取根目录NSString *homePath = [homeDictionary stringByAppendingPathComponent:@"atany.archiver"];//添加储存的文件名BOOL flag = [NSKeyedArchiver archiveRootObject:@”归档” toFile:homePath];//归档一个字符串
这种方式可以对字符串、数字等进行归档,当然也可以对NSArray与NSDictionary进行归档。返回值Flag标志着是否归档成功,YES为成功,NO为失败。
接档:
NSKeyedUnarchiver unarchiveObjectWithFile:homePath]
接下来,我们将一个Person对象进行归档,并且接归档。
1.新建Personlei类
Person.h
#import <Foundation/Foundation.h>@interface Person : NSObject@property (nonatomic, copy) NSString *name;@property (nonatomic, assign) int age;@end
Person.m
@implementation Person//解档方法- (instancetype)initWithCoder:(NSCoder *)coder{if (self=[super init]) {_name = [coder decodeObjectForKey:@"name"];_age = [coder decodeIntForKey:@"age"];}return self;}//归档方法- (void)encodeWithCoder:(NSCoder *)coder{// 成员变量_name按照name进行归档。接档时也必须是name进行解归档。同一个成员变量,归档和解档的key是一样的。[coder encodeObject:_name forKey:@"name"];[coder encodeInt:_age forKey:@"age"];}@end
2.操作归档
创建一个Person对象
Person *p = [[Person alloc] init];p.name = @"abc";p.age = 100;
将这个Person对象进行归档
#define PATH [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"account.data"][NSKeyedArchiver archiveRootObject:p toFile:PATH];//BOOL flag = [NSKeyedArchiver archiveRootObject:@”归档” toFile:homePath];//归档一个字符串
将这个Person对象进行解解归档
#define PATH [[NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) lastObject] stringByAppendingPathComponent:@"account.data"]// 返回bool值,yes表示成功。Person *p = [NSKeyedUnarchiver unarchiveObjectWithFile:PATH];
注意:以上文件名account.data后缀名可以随意写。但必须一样。是同一个文件。
这种归档的方式存在一个缺点:只能把一个对象归档进一个文件中,那么怎么对多个对象进行归档呢?
同样是使用NSKeyedArchiver进行归档,不同的是同时归档多个对象,这里我们举例放入了一个CGPoint点、字符串、整数(当然很多类型都可以的,例如UIImage、float等等),使用encodeXXX方法进行归档,最后通过writeToFile方法写入文件。
// 准备数据CGPoint point = CGPointMake(1.0, 2.0);NSString *info = @"坐标原点";NSInteger value = 10;// 文件储存路径NSString *multiHomePath = [NSHomeDirectory() stringByAppendingPathComponent:@"multi.archiver"];// 储存多个归档对象的数据NSMutableData *data = [[NSMutableData alloc]init];// 归档对象NSKeyedArchiver *archvier = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];// 对多个对象进行归档[archvier encodeCGPoint:point forKey:@"kPoint"];[archvier encodeObject:info forKey:@"kInfo"];[archvier encodeInteger:value forKey:@"kValue"];[archvier finishEncoding];// 将data写入文件。[data writeToFile:multiHomePath atomically:YES];
接档:从路径中获得数据构造NSKeyedUnarchiver实例,使用decodeXXXForKey方法获得文件中的对象。
NSMutableData *dataR = [[NSMutableData alloc]initWithContentsOfFile:multiHomePath];NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:dateR];CGPoint pointR = [unarchiver decodeCGPointForKey:@"kPoint"];NSString *infoR = [unarchiver decodeObjectForKey:@"kInfo"];NSInteger valueR = [unarchiver decodeIntegerForKey:@"kValue"];[unarchiver finishDecoding];NSLog(@"%f,%f,%@,%d",pointR.x,pointR.y,infoR,valueR);
新建归档接档的基础类,需要归档解当的类继承自它就可以
#import "KKBaseCoder.h"#import <objc/runtime.h>@implementation KKBaseCoder//归档与解归档的方法- (instancetype)initWithCoder:(NSCoder *)coder{self = [super init];if (self) {//获取所有属性NSArray * porpertyArray = [self getAllPropertys];for (NSString * name in porpertyArray) {//去掉属性名前面的_NSString * key = [name substringFromIndex:1];//约定好的键值对 c+key[self setValue:[coder decodeObjectForKey:[NSString stringWithFormat:@"a%@",key]] forKey:key];}}return self;}- (void)encodeWithCoder:(NSCoder *)coder{//获取所有属性NSArray * porpertyArray = [self getAllPropertys];for (NSString * name in porpertyArray) {//去掉属性名前面的_NSString * key = [name substringFromIndex:1];//约定好的键值对 c+key[coder encodeObject:[self valueForKey:key] forKey:[NSString stringWithFormat:@"a%@",key]];}}//获取model所有属性- (NSArray *)getAllPropertys{NSMutableArray * array = [[NSMutableArray alloc]init];unsigned int * count = malloc(sizeof(unsigned int));//调用runtime的方法//Ivar:方法返回的对象内容对象,这里将返回一个Ivar类型的指针//class_copyIvarList方法可以捕获到类的所有变量,将变量的数量存在一个unsigned int的指针中Ivar * mem = class_copyIvarList([self class], count);//进行遍历for (int i=0; i< *count ; i++) {//通过移动指针进行遍历Ivar var = * (mem+i);//获取变量的名称const char * name = ivar_getName(var);NSString * str = [NSString stringWithCString:name encoding:NSUTF8StringEncoding];[array addObject:str];}//释放内存free(count);//注意处理野指针count=nil;return array;}@end