What is the correct way to unarchive something that was archived using encodeRootObject:?
I am attempting to use the Keyed Archiver classes for the first time and I'm failing the last assert in this simple test (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 finishE开发者_Python百科ncoding];
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.");
}
I have confirmed that the archiver is archiving, I'm assuming the issue exists in the unarchiving. According to the Archives and Serializations Guide I believe that perhaps there is some issue with how I am using the Unarchiver?
Thanks!
First, you should not use the encodeRootObject
method. That's a legacy method defined in NSCoder
to support obsolete non-keyed archivers, and can only be decoded using decodeObject:
. You only use the pair of encodeObjectForKey:
and decodeObjectForKey:
.
So,
id decodedEntity = [bua decodeObjectForKey:@"root"];
should be
id decodedEntity = [bua decodeObjectForKey:@"testKey"];
If you want to decode the totality of a dictionary, instead of
[ba encodeRootObject:dict];
do
[ba encodeObject:dict forKey:@"root"];
By the way, for simple purposes it often suffices to use NSUserDefaults
, which automatically takes care of creating the file to write on, writing things on the file, and reading it when the program is launched the next time.
If you just need to encode a dictionary, using NSPropertyListSerialization
usually suffices.
If you do use NSKeyedArchiver
and NSKeyedUnarchiver
, I recommend you to follow the practice and write encodeWithCoder:
and initWithCoder:
for an object.
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);
}
精彩评论