Strange behavoir when decoding an NSArray via NSSecureCoding

元气小坏坏 提交于 2019-12-21 12:05:20

问题


i spent all afternoon banging my head against the wall trying to figure out why decoding of this class was failing. the class has a property that is an NSArray of Foo objects. Foo conforms to NSSecureCoding, and i have successfully encoded and decoded that class by itself. i was getting an error in initWithCoder: that said failed to decode class Foo. through some experimentation, i discovered that i needed to add [Foo class] to initWithCoder: in order for it to work. maybe this will help someone else who's having the same problem. my question is, why is this necessary? i found no suggestion that this is necessary in apple's documentation.

#import "Foo.h"

@interface MyClass : NSObject <NSSecureCoding>
@property (nonatomic) NSArray *bunchOfFoos;
@end

@implementation MyClass

static NSString *kKeyFoo = @"kKeyFoo";

+ (BOOL) supportsSecureCoding
{
    return YES;
}

- (void) encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:self.bunchOfFoos forKey:kKeyFoo];
}

- (id) initWithCoder:(NSCoder *)decoder
{
    if (self = [super init])
    {
        [Foo class]; // Without this, decoding fails
        _bunchOfFoos = [decoder decodeObjectOfClass:[NSArray class] forKey:kKeyFoo];
    }
    return self;
}

@end

回答1:


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.




回答2:


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.




回答3:


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.



来源:https://stackoverflow.com/questions/19579143/strange-behavoir-when-decoding-an-nsarray-via-nssecurecoding

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