一、概念
1.归档用于保存对象,包括被归档对象之间的各种相互关系或者依赖性。解档用于重建以前归档的对象与关系。在其它面向对象的语言中,一般使用术语"序列化"来描述归档解档模式。
2.归档的对象通常存储为二进制数据,可以在内存或者磁盘中读取,写入。不过在Cocoa中,也有一些对象使用XML文件进行归档和解档,比如NSArray,NSDictionary等等,这是Cocoa中关于归档解档模式的另一个体现。
3.实现归档和解档模式的关键是相关对象的处理。不管对象之间的关系有多复杂,归档中的每个对象在那个归档中只会编码一次,也就是说,如果许多归档的对象都引用相同的对象,则这个对象只会编码一次,这就最小化了归档所需的存储空间。
4.有条件的编码:在许多对象彼此相关但是并非所有关系都需要保留下来的情况下,可以有条件的选择只对某些对象进行归档。
二、Cocoa中的实现
1.NSCoding协议:
(1)当一个对象要实现归档解档操作,需要归档的对象必须要实现NSCoding协议。
(2)NSCoding协议包含两个方法:encodeWithCoder:,initWithCoder:。
(3)encodeWithCoder实现对象编码,initWithCoder实现对象解码。两个方法的参数是NSCoder类实例,是对象编码解码器,可以将实例对象的属性直接编码或者以key-value的方式编码,解码也一样。
类似的方法如下(每种数据类型都有相关的方法支持):
encodeObject:
encodeObject:forKey:
encodeInt:forKey:
decodeObject
decodeObjectForKey:
decodeIntForKey:
(4)编码和解码是对象迭代的一个过程,可能encodeObject:ObjectA方法又会引起ObjectA的encodeWithCoder被调用。
(5)NSCoding实现示例:
- (void)encodeWithCoder:(NSCoder*)coder{
[coder encodeObject:self.userName forKey:SAMPLEDATA_KEY_USERNAME];
[coder encodeInt:self.age forKey:SAMPLEDATA_KEY_AGE];
[coder encodeBool:self.gender forKey:SAMPLEDATA_KEY_GENDER];
[coder encodeObject:self.friends forKey:k_FRIENDS];
[coder encodeObject:self.address forKey:k_ADDRESS];
[coder encodeObject:self.addresses forKey:k_userEntity_addresses];
}
- (id)initWithCoder:(NSCoder*)decoder{
if (self = [super init]) {
if (decoder == nil) {
return self;
}
self.userName = [decoder decodeObjectForKey:SAMPLEDATA_KEY_USERNAME];
self.gender = [decoder decodeBoolForKey:SAMPLEDATA_KEY_GENDER];
self.age = [decoder decodeIntForKey:SAMPLEDATA_KEY_AGE];
self.friends = [decoder decodeObjectForKey:k_FRIENDS];
self.address = [decoder decodeObjectForKey:k_ADDRESS];
self.addresses = [decoder decodeObjectForKey: k_userEntity_addresses];
}
return self;
}
2.归档和解档工具类:
NSKeyedArchiver用于归档相关对象,生成NSData;
NSKeyedUnarchiver用于解档对象,从NSData解码出对象。
3.NSKeyedArchiver和NSKeyedUnarchiver相关API:
(1)NSData *data = [NSKeyedArchiver archivedDataWithRootObject:objectA];
NSObject *object = [NSKeyedUnarchiver unarchiveObjectWithData:someData];
(2)Bool isSucc = [NSKeyedArchiver archiveRootObject:rootObject toFile:filePath];
NSObject *object = [NSKeyedUnarchiver unarchiveObjectWithFile:filePath];
(3)以上两套API方便的实现单个对象的归档和解档,如果要将多个对象归档在一起,可以用以下API:
归档:
NSMutableData *data = [[NSMutableData alloc] init];
NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[archiver encodeObject:objectA forKey:@"keyA"];
[archiver encodeObject:objectB forKey:@"keyB"];
[archiver encodeInt:3 forKey:@"keyC"];
[archiver finishEncoding];
[data writeToFile:filePath atomically:YES];
[archiver release];
[data release];
解档:
– initForReadingWithData:
– decodeObjectForKey:
finishDecoding
(4)NSKeyedArchiver有一个属性outputFormat,类型为NSPropertyListFormat,指定编码器的编码格式。有两个可用的值:NSPropertyListXMLFormat_v1_0 和 NSPropertyListBinaryFormat_v1_0。采用二进制的格式比采用文本的格式占用的空间小,读写速度高。