八十七、基础框架(四十五)归档-编写 编码措施 和 解码措施

本文介绍了Objective-C中自定义类的归档与解档过程,包括遵循NSCoding协议实现encodeWithCoder:和initWithCoder:方法,以及使用NSKeyedArchiver和NSKeyedUnarchiver进行对象序列化。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

基本的Objectiv-c物件,比如  NSString、NSArray、NSDictionary、NSSet、NSDate、NSNumber  和  NSData类型的物件,都可以用  之前提到过的方法  归档  和  恢复。但是  你  不能直接  用  这样的方法  对AddressBook类型的物件  进行归档。假如  我们  硬要这样  做的话,就像  这样:

你  会收到  这样的消息:

从这些错误信息中  我们  可以发现  系统  试图  对AddressBook类型的物件  采取  encodeWithCoder:这项措施,却发现  没有  一项叫encodeWithCoder:的措施  适用于  AddressBook类型的物件。

如果  要对上面列举的类型以外的物件  进行归档,我们  必须告诉  系统  如何归档,也就是  编码  以及  如何解档,也就是  解码。我们  使AddressBook  和  AddressCard这两类物件  遵循  <NSCoding>协议。根据<NSCoding>这项协议,我们  必须编写  encodeWithCoder:  和  initWithCoder:这两项措施,并  使  之  适用于  AddressBook  和  AddressCard这两类物件。

我们  每次对  某个物件  进行归档时  archiveRootObject:toFile:这项措施  都会对  需要归档的物件  采取  encodeWithCoder:这项措施。同样  解档的时候  也会采取  initWithCoder:这项措施。

一般来说  encodeWithCoder:这项措施  是  对你希望保存的物件所包含的变量  进行  归档的。对于  基本的objective-c物件  我们  可以采取  encodeObject:forKey:这项措施。而  对于  基本的c语言数据类型  我们  可以采取  下列的措施  进行  归档  和  解档:

编码 解码
encodeBool:forKey: decodeBool:forKey:
encodeInt:forKey: decodeInt:forKey:
encodeInt32:forKey: decodeInt32:forKey:
encodeInt64:forKey: decodeInt64:forKey:
encodeFloat:forKey: decodeFloat:forKey:
encodeDouble:forKey: decodeDouble:forKey:

对objective-c中的基本物件  归档时  采取  encodeObject:forKey:这项措施,而  解档时  刚好  相反,我们  要采取  decodeObject:forKey:这项措施。

接下来  我们  需要  在AddressCard这类物件的实施文件中  添加  encodeWithCoder:  和  initWithCoder:这两项措施:

在encodeWithCoder:这项措施当中  参数encoder  是  一个NSCoder类型的物件。由于  AddressCard这类物件  包含  在NSObject这类物件当中,你  不用担心  如何对各个AddressCard类型的物件中继承自NSObject这类物件的变量  进行编码。如果  你  知道  包含AddressCard这类物件的物件类型,比如  这里的NSObject这类物件, 遵循  <NSCoding>协议,那么  你  可以在encodeWithCoder:这项措施当中  对其实施对象  采取  适用于NSObject这类物件的encodeWithCoder:这项措施:

每个AddressCard类型的物件  都包含  name  和  email两个变量。由于  他们  都是  NSString类型的物件,我们  可以对他们  采取  encodeObject:forKey:这项措施  进行编码。

encodeObject:forKey:这项措施  不但  将  物件  进行编码  而且  给  这个物件  分配  一个特定的关键字。我们  可以根据物件所对应的关键字  将  物件  读取出来。编码时  给物件的关键字  是  随记的,只要  你  在读取  物件时  使用  完全相同的关键字  就可以了。唯一可能发生冲突的情况  就是  如果  一个物件所属的类型  包含  在另一个物件所属的类型当中,而  这两个物件  却有  相同的关键字。为了  防止  冲突的发生,我们  可以在关键字前面  加上  物件所属类型的名称。

解码的过程  刚好  相反。传递给initWithCoder:这项措施的参数  是  一个NSCoder类型的物件,存储  在变量decoder当中。你  不需要考虑  这个参数,只是记住  这个参数  可以得到  你想从归档中提取的物件的信息。

同样  由于  AddressCard这类物件  包含  在NSObject这类物件当中,你  同样  不需要担心  如何对各个AddressCard类型物件中继承自NSObject这类物件的变量  进行编码。如果  你  知道  NSObject这类物件  遵循  <NSCoding>这项协议,你  可以对initWithCoder:这项措施的实施对象  采取  适用于NSObject这类物件的措施initWithCoder:,就像  这样:

与  AddressCard这类物件  类似,我们  需要编写  适用于AddressBook这类物件的编码  和  解码措施。AddressBook这类物件的接口文件中  唯一需要修改的一行  就是  @interface这行,我们  需要把  这行语句  修改成  这样:

使  AddressBook这类物件  遵循  <NSCoding>这项协议。

AddressBook这类物件的实施部分  包含了  encodeWithCoder:  和  initWithCoder:这两项措施的具体内容:

我们  通过下面的程序  来检查  适用于AddressCard  和  AddressBook这两类物件的两项措施encodeWithCoder:  和  initWithCoder:  是否正常  工作:

这个程序  先创建了  一个地址簿,然后  将  其  归档  到文件addressbook.archive当中。你  可以在encodeWithCoder:  和  initWithCoder:这两项措施中  调用  NSLog()这个函数  来验证  这两项措施  是否得到了  执行。

下面的程序  展示了  如何将  归档文件  读取  到内存,并且  “组装成”  一个完好的AddressBook类型的物件:

运行  这个程序,可以得到  这样的结果:


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值