Strange behavoir when decoding an NSArray via NSSecureCoding

允我心安 提交于 2019-12-04 04:42:14
Yuchen Zhong

For those who are still struggling with this: @Ben H's solution didn't solve my problem. And I keep having the following error message:

Terminating app due to uncaught exception 'NSInvalidUnarchiveOperationException', reason: >'value for key 'NS.objects' was of unexpected class 'ClassA'. Allowed classes are '{(
NSArray
)}'.'

And finally, I realized that for custom classes. You have to use the following function instead decodeObjectOfClasses:

- (id)decodeObjectOfClasses:(NSSet *)classes forKey:(NSString *)key

And you to pass a NSSet of all possible classes in the NSArray to the function above! I am not sure why @Ben H could solve the issue by simply adding a [Foo class] outside of the function. Maybe it is a compiler issue. But anyway, if his solution doesn't work, try this one as well.

I've just encountered similar issue and that was weird and extremely time consuming. I wanted to test my class to be NSSecureCoded correctly with Specta/Expecta. So I've implemented everything as needed specifying class when decoded. At the end of my trials I got weirdest exception:

value for key 'key' was of unexpected class 'MyClass'. Allowed classes are '{(
    MyClass
)}'.

Test looked something like that:

MyClass *myClassInstance = ...
NSMutableData *data = [NSMutableData data];
NSKeyedArchiver *secureEncoder = [[NSKeyedArchiver alloc] initForWritingWithMutableData:data];
[secureEncoder setRequiresSecureCoding:YES]; // just to ensure things

NSString *key = @"key";
[secureEncoder encodeObject:myClassInstance forKey:key];
[secureEncoder finishEncoding];

NSKeyedUnarchiver *secureDecoder = [[NSKeyedUnarchiver alloc] initForReadingWithData:data];
[secureDecoder setRequiresSecureCoding:YES];
MyClass *decodedInstance = [secureDecoder decodeObjectOfClass:[MyClass class] forKey:key]; // exception here
[secureDecoder finishDecoding];

...expect...

While plain NSCoding (requiresSecureCoding = NO) test succeeded, NSSecureCoding tests kept failing. After vast range of trials I found solution for that, just a single line:

[secureDecoder setClass:[MyClass class] forClassName:NSStringFromClass([MyClass class])];

After that all my tests succeeded, objects were created as expected.

I'm not sure why did that happened, my guess would be that class is not visible as Ben H suggested and it uses something like NSClassFromString(@"MyClass"). The above code worked fine in AppDelegate. MyClass was from development pods I'm developing.

i think i may have figured this out. without the line [Foo class], there is no reference to the class Foo in this file. because of this, i believe the compiler is optimizing the Foo class out, and then the Foo objects within the array cannot be decoded. having [Foo class] in there prevents this.

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!