【iOS】文件(对象数据)的归档和解档


简介

  • 文件归档 — 就是把需要存储的对象数据存储到磁盘上,实现数据的持久性存储和备份
  • 解档 — 就是从磁盘上读取该文件下的数据

iOS 本地存储方法:plist属性列表,归档,SQLite,CoreData

本篇文章对归档和解档进行介绍,其他方法日后学习。

对象归档是将对象以文件(二进制数据)的形式保存到磁盘中(也称为序列化,持久化),使用的时候读取该文件的保存路径,从而读取文件的内容(也称为接档,反序列化
对象归档的文件是保密的,在磁盘上无法查看文件中的内容,而属性列表是明文的,可以查看。通过文件归档产生的文件是不可见的,如果打开归档文件的话,内容是乱码的;ta不同于属性列表和plist文件是可见的,正因为不可见的缘故,使得这种持久性的数据保存更有可靠性

这是序列化某个自定义对象后的文件内容:
在这里插入图片描述

自定义对象的单个对象归档、解档

对自定义的单个对象进行归档和解归档(由于自定义对象不具有归档的性质,所以要实现归档和解归档,首先必须实现NSCoding 协议)

  1. 自定义一个Person类并实现NSCoding 协议的方法
@interface Person : NSObject <NSCoding>

@property (nonatomic, copy)NSString* name;
@property (nonatomic, assign)int age;
@property (nonatomic, assign)double weight;
//@property (nonatomic, strong)Dog* dog;

@end

@implementation Person

//NSCoder是一个抽象类
//归档的协议方法
//将归档对象协议化
- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject: self.name forKey: @"name"];
    [coder encodeInt: self.age forKey: @"age"];
    [coder encodeDouble: self.weight forKey: @"weight"];
    //[coder encodeObject: self.dog forKey: @"dog"];
}

//解档的协议方法
//将解档对象反序列化
- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        self.name = [coder decodeObjectForKey: @"name"];
        self.age = [coder decodeIntForKey: @"age"];
        self.weight = [coder decodeDoubleForKey: @"weight"];
        //self.dog = [coder decodeObjectForKey: @"dog"];
    }
    
    return self;
}

@end

  1. 初始化待归档对象并进行归档
void archiveTest(void) {
    Person* person = [[Person alloc] init];
    person.name = @"XY";
    person.age = 20;
    person.weight = 125.0;
    
//    Dog* dog = [[Dog alloc] init];
//    dog.name = @"Oudy";
//    person.dog = dog;
    
    
    BOOL isSuccess = [NSKeyedArchiver archiveRootObject: person toFile: @"/Users/jakey/Desktop/CS/Xcode/解档和归档/archiveTest.txt"];
    if (isSuccess) {
        NSLog(@"归档成功");
    } else {
        NSLog(@"归档失败");
    }
}

归档文件名称和路径自己随意设置
根据归档方法返回的BOOL值对归档的成功与否进行一个判断

  1. 归档后开始解档
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //成功归档后,注释掉
        //archiveTest();
        //解档此文件
        Person* person = [NSKeyedUnarchiver unarchiveObjectWithFile: @"/Users/jakey/Desktop/CS/Xcode/解档和归档/archiveTest.txt"];
        
        NSLog(@"%@ %d %f", person.name, person.age, person.weight);
        //NSLog(@"%@ %d %f %@", person.name, person.age, person.weight, person.dog.name);
    }
    return 0;
}

请添加图片描述
可以看到成功从本地文件中读取出已存储的对象数据

在以上过程中,可以看到本人注释掉的自定义类Dog的dog属性,这是为了说明如果存在有嵌套类(复合类),那么内层的类也需要实现NSCoding 协议,否则程序会崩溃,如下

@interface Dog : NSObject <NSCoding>

@property (nonatomic, copy)NSString* name;

@end

@implementation Dog

- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject: self.name forKey: @"name"];
}

- (instancetype)initWithCoder:(NSCoder *)coder
{
    self = [super init];
    if (self) {
        self.name = [coder decodeObjectForKey: @"name"];
    }
    return self;
}

@end

多个对象归档、解档

以上的做法中,一个文件仅归档一个对象,对于大工程量的项目这样做肯定是极其耗费时间及精力的
接下来来看如何将多个对象归档到一个文件里去

使用数组

  1. 我们可以用数组存储多个对象,然后将数组这一对象进行归档和解档
void archiveTest(void) {
    Person* person1 = [[Person alloc] init];
    person1.name = @"XY";
    person1.age = 20;
    person1.weight = 125.0;
    
    Person* person2 = [[Person alloc] init];
    person2.name = @"ZA";
    person2.age = 19;
    person2.weight = 130.0;
    
    Person* person3 = [[Person alloc] init];
    person3.name = @"BC";
    person3.age = 21;
    person3.weight = 135.0;
    
    NSArray* array = @[person1, person2, person3];
    BOOL isSuccess = [NSKeyedArchiver archiveRootObject: array toFile: @"/Users/jakey/Desktop/CS/Xcode/解档和归档/archiveTest.txt"];
    if (isSuccess) {
        NSLog(@"归档成功");
    } else {
        NSLog(@"归档失败");
    }
}
  1. 进行解归档(归档时,如果目标文件之前存有数据,那么新的归档数据会将原文件完全覆盖
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //成功归档后,注释掉
        //archiveTest();
        //解档
        NSArray* array = [NSKeyedUnarchiver unarchiveObjectWithFile: @"/Users/jakey/Desktop/CS/Xcode/解档和归档/archiveTest.txt"];
        
        for (Person* person in array) {
            NSLog(@"%@ %d %f", person.name, person.age, person.weight);
        }
    }
    return 0;
}

结果如下:
请添加图片描述
解档成功!

多对象归档和解档

上个方法是将多个对象转化成一个对象进行归档解档,实际上还是针对单个对象进行操作,局限性仍然很大,下面介绍多对象归档和解档

  1. 初始化多个对象数据并进行归档
void archiveTest(void) {
    Person* person1 = [[Person alloc] init];
    person1.name = @"XY";
    person1.age = 20;
    person1.weight = 125.0;
    
    Person* person2 = [[Person alloc] init];
    person2.name = @"ZA";
    person2.age = 19;
    person2.weight = 130.0;
    
    Person* person3 = [[Person alloc] init];
    person3.name = @"BC";
    person3.age = 21;
    person3.weight = 135.0;
    
    NSMutableData* data = [NSMutableData data];
    
    //根据二进制流创建归档对象
    NSKeyedArchiver* archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: data];
    //对对象进行归档操作
    [archiver encodeObject: person1 forKey: @"person1"];
    [archiver encodeObject: person2 forKey: @"person2"];
    [archiver encodeObject: person3 forKey: @"person3"];
    //结束归档
    [archiver finishEncoding];
    
    BOOL isSuccess = [data writeToFile:@"/Users/jakey/Desktop/CS/Xcode/解档和归档/archiveTest.txt" atomically: YES];

    if (isSuccess) {
        NSLog(@"归档成功");
    } else {
        NSLog(@"归档失败");
    }
}
  1. 对多个对象进行解档
int main(int argc, const char * argv[]) {
    @autoreleasepool {
        //成功归档后,注释掉
        //archiveTest();
        
        NSData* data = [NSData dataWithContentsOfFile: @"/Users/jakey/Desktop/CS/Xcode/解档和归档/archiveTest.txt"];
        NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: data];
        
        Person* person1 = [unarchiver decodeObjectForKey: @"person1"];
        Person* person2 = [unarchiver decodeObjectForKey: @"person2"];
        Person* person3 = [unarchiver decodeObjectForKey: @"person3"];
        
        [unarchiver finishDecoding];
        
        NSLog(@"%@ %d %f", person1.name, person1.age, person1.weight);
        NSLog(@"%@ %d %f", person2.name, person2.age, person2.weight);
        NSLog(@"%@ %d %f", person3.name, person3.age, person3.weight);
        
    }
    return 0;
}

运行结果
在这里插入图片描述
这样就实现了对多个对象进行解档和归档!

归档在开发中的简单应用例子

在这里插入图片描述

我们日常使用微博时,刷到某个页面的某个位置然后退出并关闭应用,然后断开网络重新打开微博,仍会显示上次的界面,这就是因为程序将这个页面的数据进行了归档,缓存在了本地,打开时进行解档就会显示原页面

不这样做的话,再次打开页面就会显示空白页面,影响用户体验

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值