由于直接写入plist文件的局限性,不能够存储自定义对象,所以就有了归档,NSString、NSDictionary、NSArray、NSData、NSNumber等类型的对象,可以直接用NSKeyedArchiver进行归档和恢复,因为它们内部实现了NSCoding协议,比如NSString实现了NSSecureCoding,而NSSecureCoding实现了NSCoding协议,不是所有的对象都可以直接用这种方法进行归档,只有遵守了NSCoding协议的对象才可以,而归档和解档的过程很像我们在URL请求的时候进行encode和decode的过程,而在归档自定义对象的时候,如果子类对象也需要归档那么,在子类对象实现encodeWithCoder和initWithCoder方法的时候要先调用父类的encodeWithCoder和initWithCoder。
归档的特点:
//获取document目录
//NSUserDomainMask从用户文件夹开始找 YES代表代表展开路径中的波浪字符“~”
NSArray *documet=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *doc=documet[0];
//归档 如果归档为plist文件不需要用load的方式加载
NSString *ahPath=[doc stringByAppendingString:@"array.archive"];
NSArray *arr=@[@"book1",@"book2",@"book3"];
//归档
[NSKeyedArchiver archiveRootObject:arr toFile:ahPath];
//解档
NSArray *unarray= [NSKeyedUnarchiver unarchiveObjectWithFile:ahPath];
NSLog(@"array==%@",unarray);
@implementation Person
//归档
-(void)encodeWithCoder:(NSCoder *)aCoder{
[aCoder encodeObject:_name forKey:@"name"];
[aCoder encodeInt:_age forKey:@"age"];
NSData *imageData=UIImagePNGRepresentation(_image);
[aCoder encodeObject:imageData forKey:@"imageData"];
}
//接档
-(id)initWithCoder:(NSCoder *)aDecoder{
self=[super init];
if (self) {
[self setName:[aDecoder decodeObjectForKey:@"name"]];
[self setAge:[aDecoder decodeIntForKey:@"age"]];
NSData *imageData=[aDecoder decodeObjectForKey:@"imageData"];
NSLog(@"%@",imageData);
[self setImage:[UIImage imageWithData:imageData]];
}
return self;
}
+(id)initPersonWithName:(NSString *)name age:(int)age image:(UIImage *)image{
Person *person=[[Person alloc]init];
[person setName:name];
[person setAge:age];
[person setImage:image];
return person;
}
@end
@implementation Student
-(id)initWithCoder:(NSCoder *)aDecoder{
self=[super initWithCoder:aDecoder];
if (self) {
_no=[aDecoder decodeObjectForKey:@"no"];
}
return self;
}
-(void)encodeWithCoder:(NSCoder *)aCoder{
[super encodeWithCoder:aCoder];
[aCoder encodeObject:_no forKey:@"no"];
}
+(id)initPersonWithName:(NSString *)name age:(int)age image:(UIImage *)image no:(NSString *)no{
Student *stu=[[Student alloc]init];
[stu setNo:no];
[stu setAge:age];
[stu setImage:image];
[stu setName:name];
return stu;
}
@end NSArray *arry=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *doc=arry[0];
Person *person=[Person initPersonWithName:_nameText.text age:_ageText.text.intValue image:_iconView.image];
NSString *path=[doc stringByAppendingString:@"person.plist"];
[NSKeyedArchiver archiveRootObject:person toFile:path];NSArray *arry=NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *dir=arry[0];
NSString *path=[dir stringByAppendingString:@"person.plist"];
Person *person= [NSKeyedUnarchiver unarchiveObjectWithFile:path];
_nameText.text=person.name;
_ageText.text=[NSString stringWithFormat:@"%d",person.age];
_iconView.image=person.image;
NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [documents[0]stringByAppendingPathComponent:@"multiPersonInfo.plist"];
Person *person1=[Person initPersonWithName:@"san" age:_ageText.text.intValue image:_iconView.image];
Person *person2=[Person initPersonWithName:@"zhang" age:_ageText.text.intValue image:_iconView.image];
Student *stu=[Student initPersonWithName:@"lisi" age:10 image:_iconView.image no:@"89757"];
// 新建一块可变的数据区
NSMutableData *data = [NSMutableData data];
// 将数据区连接到一个NSKeyedArchiver对象
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc]initForWritingWithMutableData:data];
// 开始存档对象,存档的数据都会存储到NSMutableData中
[archiver encodeObject:person1 forKey:@"person1"];
[archiver encodeObject:person2 forKey:@"person2"];
// 存档完毕(一定要调用这个方法!!!)
[archiver finishEncoding];
// 将存档的数据写入文件
[data writeToFile:path atomically:YES]; NSArray *documents = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *path = [documents[0]stringByAppendingPathComponent:@"multiPersonInfo.plist"];
NSData *data = [NSData dataWithContentsOfFile:path];
// 根据数据,解析成一个NSKeyedUnarchiver对象
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc]initForReadingWithData:data];
// 恢复对象
Person *person1 = [unarchiver decodeObjectForKey:@"person1"];
Person *person2 = [unarchiver decodeObjectForKey:@"person2"];
// 恢复完毕(一定要调用这个方法)
[unarchiver finishDecoding];
NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
[defaults setObject:@"张三" forKey:@"userName"];
[defaults setInteger:10 forKey:@"age"];
[[NSUserDefaults standardUserDefaults]setObject:@"mimaya" forKey:@"password"];
//同步 如果不加会延迟
[defaults synchronize];读取偏好设置NSUserDefaults *defaults=[NSUserDefaults standardUserDefaults];
NSString *name=[defaults objectForKey:@"userName"];
NSLog(@"userName=%@",name);
注意:UserDefaults设置数据时,不是立即写入,而是根据时间戳定时地把缓存中的数据写入本地磁盘。所以调用了set方法之后数据有可能还没有写入磁盘,应用程序就终止了,出现以上问题,可以通过调用synchornize方法强制写入。
原文:http://blog.csdn.net/richerg85/article/details/20456969