可以使用NSKeyedArchiver
把数据保存到本地,在需要使用数据的时候使用NSKeyedUnarchiver
来读取数据,简单的数据如下
- (void)saveAndReadSimpleData
{
NSArray *array = @[@"1", @"2", @"3"];
[NSKeyedArchiver archiveRootObject:array toFile:[self filePath]];
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithFile:[self filePath]];
}
- (NSString *)filePath
{
NSString *documentPath = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES).firstObject;
return [documentPath stringByAppendingPathComponent:@"array.data"];
}```
但是大多数时候需要保存的数据都是自定义类的实例,例如我们有一个`Person`类,拥有`name`和`age`两个属性
@interface Person : NSObject
@property(nonatomic, copy) NSString *name;
@property(nonatomic, assign) NSInteger age;
@end
在使用上同上
-
(void)saveAndReadCustomData
{
Person *p = [Person new];
p.name = @"JC";
p.age = 88;[NSKeyedArchiver archiveRootObject:p toFile:[self filePath]];
Person *person = [NSKeyedUnarchiver unarchiveObjectWithFile:[self filePath]];
}
编译运行的时候程序会奔溃并伴随如下的错误
`*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Person encodeWithCoder:]: unrecognized selector sent to instance 0x7fe1c872ec20'`
这是因为使用自定义的类进行归档和解档的时候需要实现协议`NSCoding`
在`Person.m`文件中实现`NSCoding`协议的两个方法
(instancetype)initWithCoder:(NSCoder *)coder
{
// self = [super initWithCoder:coder];
//这里需要特别注意,调用的是super的init方法而不是initWithCoder:coder方法
self = [super init];
if (self) {
self.name = [coder decodeObjectForKey:@"name"];
self.age = [coder decodeIntegerForKey:@"age"];
}
return self;
}(void)encodeWithCoder:(NSCoder *)aCoder
{
[aCoder encodeObject:self.name forKey:@"name"];
[aCoder encodeInteger:self.age forKey:@"age"];
}
再次运行程序,错误消失,能正常地进行归档和解档
######这里需要特别注意的是在`- (instancetype)initWithCoder:(NSCoder *)coder`方法中,调用的是`self = [super init];`,而不是`self = [super initWithCoder:coder];`,调用后面的方法会报父类没有相应方法的错误#####