解档归档是存储方法之一,我们先来回忆一下都有哪些存储方法。
一.回忆存储方法:
- XML归档解档
- NSUserDefault
- NSKeyedArchiver归档解档
- sqlite
1.XML归档解档
1)数据类型只支持 NSString、NSDictionary、NSArayy、NSData、NSNumber(如果你想的话,可以将基本数据类型转换为NSNumber再进行归档)
2)一般保存.plist文件
3)运用:
NSArray *array = @[@"test",@"test2"];
NSString *path3 = [[NSHomeDirectory() stringByAppendingPathComponent:@"Desktop"]stringByAppendingPathComponent:@"array.plist"];
// 归档
[array writeToFile:path3 atomically:YES];
// 解档
NSArray *array = [NSArray arrayWithContentsOfFile:path3];
2.NSUserDefault
用于保存一些程序配置信息
NSString *passWord = @"88888888";
NSUserDefaults *user = [NSUserDefaults standardUserDefaults];
[user setObject:passWord forKey:@"passWord"];
// 通过存储时候key取出相应的value
NSString *passWord = [ user objectForKey:@"passWord"];
可学习:
https://www.cnblogs.com/silence-wzx/p/5143113.html
3. NSKeyedArchiver归档解档
- 将一个Objective-C对象转换成NSData的操作叫做对象的序列化;
- 而将一个NSData转换成Objective-C对象的操作叫做对象的反序列化。
- 一个Objective-C对象需要通过实现NSCoding协议以便支持序列化与反序列化
二.NSKeyedArchiver归档解档
需求:
有一个Person,需要对其属性进行赋值,可以存储到本地,也可以从本地读取。
Person类:
.h:
@interface Person : NSObject//实现协议才可使用NSKeyedArchiver归解档
//要归档的属性
//姓名
@property(nonatomic,strong)NSString * name;
//年龄
@property(nonatomic,assign)int age;
@end
.m:
@implementation Person
//进行归档
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInt:self.age forKey:@"age"];
}
//进行解档
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
if ([super init]) {
self.name = [aDecoder decodeObjectForKey:@"name"];
self.age = [aDecoder decodeIntForKey:@"age"];
}
return self;
}
@end
controller里面,对person赋值、存取:
- (void)viewDidLoad {
[super viewDidLoad];
//给person对象赋值
Person * person = [[Person alloc] init];
person.name = @"lyttt";
person.age = 18;
NSString * tempPath = NSTemporaryDirectory();
tempPath = [tempPath stringByAppendingString:@"/personInfo1.data"];
//存数据
[self savePersonInfo:person path:tempPath];
//取出数据
[self readPersonInfoWithPath:tempPath];
}
//存数据
-(void)savePersonInfo:(Person *)person path:(NSString *)path{
BOOL saveResult = [NSKeyedArchiver archiveRootObject:person toFile:path];
NSLog(@"保存是否成功:%d",saveResult);
}
//取数据
-(void)readPersonInfoWithPath:(NSString *)path{
Person * getPerson = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSLog(@"person name:%@,person age:%d",getPerson.name,getPerson.age);
}
上面的代码就可以实现归档解档,如果Person里面有10多个、20多个属性的话,我们再person里面对每个属性归解档就太麻烦。我们就运用runtime的方法了。主要运用runtime可以读取所有属性的方法。
如下:
//进行归档
-(void)encodeWithCoder:(NSCoder *)aCoder{
// [aCoder encodeObject:self.name forKey:@"name"];
// [aCoder encodeInt:self.age forKey:@"age"];
//使用runtime进行归档
unsigned int outCount = 0;
Ivar * ivars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i++) {
const char * varCharName = ivar_getName(ivars[i]);
NSString * varName = [NSString stringWithFormat:@"%s",varCharName];
[aCoder encodeObject:[self valueForKey:varName] forKey:varName];
}
}
//进行解档
-(instancetype)initWithCoder:(NSCoder *)aDecoder{
if ([super init]) {
// self.name = [aDecoder decodeObjectForKey:@"name"];
// self.age = [aDecoder decodeIntForKey:@"age"];
//使用runtime进行解档
unsigned int outCount = 0;
Ivar * ivars = class_copyIvarList([self class], &outCount);
for (int i = 0; i < outCount; i++) {
const char * varCharName = ivar_getName(ivars[i]);
NSString * varName = [NSString stringWithFormat:@"%s",varCharName];
[self setValue:[aDecoder decodeObjectForKey:varName] forKey:varName];
}
}
return self;
}
c语言里面:函数参数如果是基本数据类的指针,基本上是需要在内部修改它的值。例如在归档解档时候的outCount值,原本是0,传入的是指针,再获取outCount值的时候已经是属性的个数。