Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Strange behavoir when decoding an NSArray via NSSecureCoding

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
like image 556
Ben H Avatar asked Oct 25 '13 00:10

Ben H


2 Answers

Yuchen's answer is/was on the right track but the important thing to know is that the NSSet parameter needs to include the class for the collection in addition to the custom class, like so:

_bunchOfFoos = [decoder decodeObjectOfClasses:[NSSet setWithObjects:[NSArray class], [Foo class], nil] forKey:kKeyFoo];

At least that's what seems to be working for me at this point...

like image 183
Christopher King Avatar answered Oct 30 '22 14:10

Christopher King


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.

like image 36
Yuchen Avatar answered Oct 30 '22 12:10

Yuchen