我第一次尝试使用键控存档器类,但在这个简单的测试(OCUnit)中,我的最后一个断言失败了:
- (void) testNSCoding
{
NSMutableDictionary *dict = [NSMutableDictionary dictionaryWithCapacity:5];
[dict setObject:@"hello" forKey:@"testKey"];
NSMutableData* data = [NSMutableData data];
NSKeyedArchiver *ba = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[ba encodeRootObject:dict];
[ba finishEncoding];
STAssertTrue(data.length != 0, @"Archiver gave us nothing.");
NSKeyedUnarchiver *bua = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
id decodedEntity = [bua decodeObjectForKey:@"root"];
[bua finishDecoding];
STAssertNotNil(decodedEntity, @"Unarchiver gave us nothing.");
}
我已经确认存档程序正在存档,我假设问题存在于取消存档中。根据存档和序列化指南,我相信我如何使用Unarchiver可能存在一些问题?
谢谢!
首先,不应使用 encodeRootObject
方法。这是 NSCoder
中定义的一种传统方法,用于支持过时的非密钥存档器,并且只能使用 decodeObject:
进行解码。您只使用encodeObjectForKey:
和decodeObjectForKey:
对。
所以
id decodedEntity = [bua decodeObjectForKey:@"root"];
应该是
id decodedEntity = [bua decodeObjectForKey:@"testKey"];
如果要解码字典的整体,而不是
[ba encodeRootObject:dict];
做
[ba encodeObject:dict forKey:@"root"];
顺便说一下,出于简单目的,通常使用NSUserDefaults
就足够了,它会自动负责创建要写入的文件,在文件上写入内容,并在下次启动程序时读取它。
如果您只需要对字典进行编码,使用NSPropertyListSerialization
通常就足够了。
如果您确实使用NSKeyedArchiver
和NSKeyedUnarchiver
,我建议您遵循惯例并为对象编写encodeWithCoder:
和initWithCoder:
。
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
id profileData = [defaults dataForKey:kProfileDataKey]; // or you can get it from the web
if (profileData && [profileData isKindOfClass:[NSData class]]) {
NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData:(NSData *)profileData];
unarchiver.requiresSecureCoding = YES; // <NSSecureCoding>
id object = [unarchiver decodeObjectOfClass:[MyClass class] forKey:NSKeyedArchiveRootObjectKey];
NSLog(@"%@", object);
}