Strange behavior when decoding NSArray through NSSecureCoding

I spent the whole day hitting my head against a wall, trying to understand why decoding of this class does not work. the class has the NSArray property of Foo objects. Foo corresponds to NSSecureCoding, and I have successfully coded and decrypted this class on its own. I was getting an error in initWithCoder: it failed to decode the Foo class. through some experiments, I found that I need to add [Foo class] to initWithCoder: for it to work. maybe this will help someone else who has the same problem. my question is why is this necessary? I did not find any suggestion that this is necessary in the Apple 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 
+7
ios objective-c nsarray nscoding nssecurecoding
source share
3 answers

I think I may have figured this out. without the string [Foo class], there is no reference to the Foo class in this file. because of this, I believe that the compiler optimizes the Foo class, and then the Foo objects in the array cannot be decoded. having a [Foo class] there prevents this.

+2
source share

For those still struggling with this: @Ben H's solution did not solve my problem. And I get the following error message:

Application terminated due to the uncaught exception "NSInvalidUnarchiveOperationException", reason:> "The value for the key" NS.objects "was an unexpected class" ClassA ". Valid classes: {{NSArray
)} ''

And finally, I figured this out for custom classes. Instead, you should use the following decodeObjectOfClasses function:

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

And you must pass the NSSet all possible classes to the NSArray function above! I'm not sure why @Ben H could solve the problem by simply adding [Foo class] outside the function. Perhaps this is a compiler problem. But in any case, if his solution does not work, try this as well.

+3
source share

I just ran into a similar problem and it was weird and extremely time consuming. I wanted to test my class for the correctness of NSSecureCoded with Specta / Expecta . Thus, I implemented everything as needed, defining the class when decoding. At the end of my tests, I received a strange exception:

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

The test looked something like this:

 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 normal NSCoding testing (requireSecureCoding = NO) was successful, NSSecureCoding tests continued to fail. After a wide range of tests, I found a solution for this, just one line:

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

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

I'm not sure why this happened, I assume that the class will not display as Ben H , and it uses something like NSClassFromString(@"MyClass") . The above code worked fine in AppDelegate. MyClass was one of the developers I'm developing.

+3
source share

All Articles