本篇文章使用NSKeyedArchiver和NSKeyedUnarchiver进行iOS的归档解档
//沙盒根目录
NSString *docPath = NSHomeDirectory();
//完整的文件路径
NSString *path = [docPath stringByAppendingPathComponent:@"Documents/numbers.plist"];
NSArray *numbers = @[@"one",@"two"];
//将数据归档到path文件路径里面
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:numbers requiringSecureCoding:NO error:nil];
BOOL success = [data writeToFile:path atomically:NO];
if (success) {
NSLog(@"文件归档成功");
} else {
NSLog(@"文件归档失败");
}
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) firstObject];
NSString *path = [docPath stringByAppendingPathComponent:@"numbers.plist"];
NSData *data = [NSData dataWithContentsOfFile:path];
NSArray *numbers = [NSKeyedUnarchiver unarchivedObjectOfClass:[NSArray class] fromData:data error:nil];
NSLog(@"numbers = %@", numbers);
上面的例子是将单个的数组或者单个字典归档到一个文件。其实我们也可以将多个数组、字典、字符串、数组等内容归档到同一个文件里面去。
NSDictionary *dic = @{@"one":@"hello",
@"two":@1};
NSInteger age = 10;
NSMutableData *data = [NSMutableData data];
//创建归档对象,归档的数据需要写入data
NSKeyedArchiver *arch = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
//键值对形式存储归档数据
[arch encodeObject:dic forKey:@"Dic"];
[arch encodeInteger:age forKey:@"Age"];
//结束归档
[arch finishEncoding];
NSString *docPath = NSHomeDirectory();
NSString *manyPath = [docPath stringByAppendingPathComponent:@"Documents/manyData.plist"];
//将归档的数据写入文件
[data writeToFile:manyPath atomically:YES];
//创建解档对象
NSString *docPath = NSHomeDirectory();
NSString *manyPath = [docPath stringByAppendingPathComponent:@"Documents/manyData.plist"];
NSData *arrayData = [NSData dataWithContentsOfFile:manyPath];
NSKeyedUnarchiver *unarch = [[NSKeyedUnarchiver alloc] initForReadingFromData:arrayData error:nil];
//根据键值得到对应数据
NSDictionary *dic = [unarch decodeObjectForKey:@"Dic"];
NSInteger age = [unarch decodeIntegerForKey:@"Age"];
//解档结束
[unarch finishDecoding];
NSLog(@"%@", dic);
NSLog(@"%ld", age);
上面的例子,归档的内容都是系统Foundation框架提供的类以及一些基本的数据类型。
Foundation框架提供的类都是实现了NSCoding协议的,所以能够直接进行归档。
如果我们自己自定义了一个类,例如Person类,是无法能够直接将这个类进行归档操作的。
如果想要对自定义的类创建出来的对象进行归档,我们需要先实现NSCoding协议。
@interface Student : NSObject
<NSCoding>
@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger grade;
@end
#import "Student.h"
@implementation Student
//NSCoding协议方法:将需要归档的属性进行归档
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeInteger:self.grade forKey:@"grade"];
[coder encodeObject:self.name forKey:@"name"];
}
//NSCoding协议方法:将需要解档的属性进行解档
- (instancetype)initWithCoder:(NSCoder *)coder {
if (self = [super init]) {
self.name = [coder decodeObjectForKey:@"name"];
self.grade = [coder decodeIntegerForKey:@"grade"];
}
return self;
}
此处使用另一种获取目录方法
//沙盒ducument目录
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//完整的文件路径
NSString *path = [docPath stringByAppendingPathComponent:@"student.archiver"];
Student *student = [[Student alloc] init];
student.name = @"dd";
student.grade = 22;
//将数据归档到path文件路径里面
BOOL success = [NSKeyedArchiver archiveRootObject:student toFile:path];
if (success) {
NSLog(@"归档成功");
}else {
NSLog(@"归档失败");
}
NSString *docPath = [NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES) objectAtIndex:0];
//完整的文件路径
NSString *path = [docPath stringByAppendingPathComponent:@"student.archiver"];
Student *student = [NSKeyedUnarchiver unarchiveObjectWithFile:path];
NSLog(@"student's name = %@, student's grade = %lu", student.name, student.grade);
//文件夹是否存在
BOOL fileExists = [[NSFileManager defaultManager] fileExistsAtPath:dir isDirectory:nil];
if (!fileExists) {
NSLog(@"文件夹不存在");
NSError *error = nil;
[[NSFileManager defaultManager] createDirectoryAtPath:dir withIntermediateDirectories:YES attributes:nil error:&error];
if (error) {
NSLog(@"error == %@", error.description);
} else {
NSLog(@"success");
}
}
//查看是否有写入权限
if (![[NSFileManager defaultManager] isWritableFileAtPath:dir]) {
NSLog(@"目录无写入权限");
}
文章参考文献:【iOS】数据持久化:使用NSKeyedArchiver进行数据归档