使用NSKeyedArchiver保存本地数据

可以使用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];`,调用后面的方法会报父类没有相应方法的错误#####

你可能感兴趣的:(使用NSKeyedArchiver保存本地数据)