开发者

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);
    }
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜