当前位置: 首页 > news >正文

NSCoding 与归档解档

NSCoding 是一个协议,用于支持对象的序列化和反序列化,也就是“归档”和“解档”操作。归档的过程将对象保存为数据,可以存储到磁盘、数据库或者传输到网络,而解档是将这些数据恢复为原始的对象。

NSCoding 协议

NSCoding 协议有两个主要方法:

  1. encodeWithCoder:: 将对象的状态编码成数据,这个方法在归档过程中被调用。
  2. initWithCoder:: 从数据中解码并还原对象的状态,这个方法在解档时被调用。

为什么使用 NSCoding?

  • 数据持久化:将对象的状态保存到文件中,使得在应用关闭后仍然能恢复这些对象的状态。
  • 数据传输:通过网络发送对象时,可以先将对象归档成二进制格式,再进行传输。
  • 缓存:将对象缓存到磁盘,以便下次使用,避免重复计算或请求。

如何实现 NSCoding?

要让一个类支持归档和解档,必须遵守 NSCoding 协议,具体实现两个方法:encodeWithCoder:initWithCoder:

示例

假设我们有一个 Person 类,需要将其归档并解档:

1. Person 类实现 NSCoding 协议
#import <Foundation/Foundation.h>

@interface Person : NSObject <NSCoding>

@property (nonatomic, strong) NSString *name;
@property (nonatomic, assign) NSInteger age;

- (instancetype)initWithName:(NSString *)name age:(NSInteger)age;

@end

@implementation Person

- (instancetype)initWithName:(NSString *)name age:(NSInteger)age {
    self = [super init];
    if (self) {
        _name = name;
        _age = age;
    }
    return self;
}

#pragma mark - NSCoding

// 归档(编码)
- (void)encodeWithCoder:(NSCoder *)coder {
    [coder encodeObject:self.name forKey:@"name"];
    [coder encodeInteger:self.age forKey:@"age"];
}

// 解档(解码)
- (instancetype)initWithCoder:(NSCoder *)coder {
    self = [super init];
    if (self) {
        _name = [coder decodeObjectForKey:@"name"];
        _age = [coder decodeIntegerForKey:@"age"];
    }
    return self;
}

@end
2. 使用 NSKeyedArchiver 和 NSKeyedUnarchiver 进行归档和解档
// 创建一个 Person 对象
Person *person = [[Person alloc] initWithName:@"Alice" age:30];

// 归档:将 Person 对象转换成 NSData,并保存到文件中
NSData *data = [NSKeyedArchiver archivedDataWithRootObject:person];

// 保存到文件
NSString *filePath = [NSTemporaryDirectory() stringByAppendingPathComponent:@"person.archive"];
[data writeToFile:filePath atomically:YES];

// 解档:从文件中读取数据并恢复成 Person 对象
NSData *savedData = [NSData dataWithContentsOfFile:filePath];
Person *decodedPerson = [NSKeyedUnarchiver unarchiveObjectWithData:savedData];

// 输出解档后的对象信息
NSLog(@"Name: %@, Age: %ld", decodedPerson.name, (long)decodedPerson.age);
3. 解释代码
  • 归档
    • 使用 NSKeyedArchiverPerson 对象转化为 NSData。其中,encodeWithCoder: 方法会被自动调用,将对象的属性保存到数据中。
    • 归档后的数据可以保存到文件、数据库或发送到网络。
  • 解档
    • 使用 NSKeyedUnarchiverNSData 解析为 Person 对象。此时,initWithCoder: 方法被调用,解码过程会根据保存时的 key 恢复对象的状态。

实际应用场景

  1. 用户数据持久化
    • 当用户退出应用时,保存用户信息(如用户名、头像、登录状态等)到本地,当再次启动应用时,恢复这些信息。
  2. 缓存数据
    • 将网络请求得到的结果(如图片、文章内容等)进行归档,缓存到本地,下次启动应用时直接读取缓存,减少网络请求。
  3. 对象序列化与反序列化
    • 在 iOS 应用中,常常需要将对象数据存储到 UserDefaults 或数据库中,使用归档可以非常方便地将对象数据存储和恢复。

注意事项

  • 归档对象需要遵守 NSCoding 协议:只有实现了 encodeWithCoder:initWithCoder: 的类才支持归档。

  • 对象中引用的其他对象也需要遵守 NSCoding 协议:如果一个对象的属性是另一个对象(比如 Person 中的 address 是一个 Address 对象),那么 Address 类也需要实现 NSCoding,否则在归档和解档时会出错。

  • 避免归档非必要属性:对于不需要归档的属性(比如临时计算值、私有变量等),可以在归档过程中忽略。可以通过 @property@dynamic 来排除一些字段的归档。

  • iOS 10 之后,归档和解档的 API 被弃用

    • iOS 10 后,NSKeyedArchiverNSKeyedUnarchiver 被一些新的方法所替代(如 NSKeyedArchiver.archivedData(withRootObject:)),为了避免未来的兼容性问题,建议使用新的归档 API。

相关文章:

  • wordpress资讯类网站整站打包
  • AcWing——3722. 骑车路线
  • Linux:ASoC 声卡驱动框架简介
  • nginx 实战配置
  • Pinia入门
  • 【20250215】二叉树:144.二叉树的前序遍历
  • 电脑桌面便利贴,备忘录软件哪个好?
  • vue-cli-service权限不足(Linux运行vue)
  • CAS单点登录(第7版)25.通知
  • 腾讯大数据基于 StarRocks 的向量检索探索
  • Android ListPreference使用
  • Java八股文详细文档.3(基于黑马、ChatGPT、DeepSeek)
  • 大话风险-风险模型监测三道防线
  • 在 Mac ARM 架构上使用 nvm 安装 Node.js 版本 16.20.2
  • Springboot核心:统一异常处理
  • QEMU 搭建 Ubuntu x86 虚拟机
  • Stable diffusion只换衣服的方法
  • 计算机网络知识速记 :HTTP多个TCP连接的实现方式
  • 在蓝耘平台使用4090显卡跑一下深度学习算法-教学文章
  • ‌OpenAI GPT-4.5技术详解与未来展望
  • 竞彩湃|德甲欧冠资格竞争白热化,伯恩茅斯主场迎恶战
  • 龙湖集团:今年前4个月销售220.8亿元,4月新增两块土地储备
  • 碧桂园:砸锅卖铁保交房、持续推进保主体,尽快让公司恢复正常经营
  • 习近平会见古巴国家主席迪亚斯-卡内尔
  • 19个剧团15台演出,上海民营院团尝试文旅融合新探索
  • 71岁导演詹姆斯・弗雷病逝,曾执导《纸牌屋》、麦当娜MV