@kingw
2016-04-23T10:13:53.000000Z
字数 4182
阅读 1221
归档 接档: 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