i am on macOS 10.15 (bigSUr), XCode 12, objective-c not ios.
I have document based app. It has a simple object "SHGlobalAppData" (NSObject) that contains a property object of a custom class "SHSetupDataModel" (NSObject).
When loading, initWithCoder returns nil for a saved value. Why?
This is the implementation:
I use NSSecureCoding, therefore both SHSetupDataModel and SHGlobalAppData have included the appropriate class method
+ (BOOL)supportsSecureCoding { return YES;}
Saving is done within NSDocument with secure coding
- (NSData *)dataOfType:(NSString *)typeName error:(NSError **)outError {
NSKeyedArchiver* archiver=[[NSKeyedArchiver alloc] initRequiringSecureCoding:YES];
[archiver encodeObject:self.appData forKey:@"appData"]; // SHSetupDataModel is a property of appData object
//[...]
}
When it comes to saving, this is the code for SHGlobalAppData
- (void)encodeWithCoder:(NSCoder *)coder {
// Other properties here
if (_setupData){
// Tests
NSLog(@"%@",[_setupData className]); // returns "SHSetupDataModel"
BOOL test = [_setupData isKindOfClass:[SHSetupDataModel class]]; // returns TRUE
[coder encodeObject:_setupData forKey:@"setupData"];
}
}
The above saving runs through smoothly. Tests are fine.
Now when loading the saved file, the following NSDocument method is invoked:
- (BOOL)readFromURL:(NSURL *)url ofType:(NSString *)typeName error:(NSError *__autoreleasing _Nullable *)outError {
NSData* data = [[NSData alloc] initWithContentsOfURL:url];
NSKeyedUnarchiver* unarchiver = [[NSKeyedUnarchiver alloc] initForReadingFromData:data error:outError];
[unarchiver setRequiresSecureCoding:YES];
// Load appData
SHGlobalAppData* appData = [unarchiver decodeObjectOfClass:[SHGlobalAppData class] forKey:@"appData"];
[unarchiver finishDecoding];
// [...]
}
This invokes the initWithCoder method form SHGlobalAppData - where i get a nil result
- (id)initWithCoder:(NSCoder *)coder {
self = [super initWithCoder:coder];
if (self) {
if ([coder containsValueForKey:@"setupData"]){
_setupData = [coder decodeObjectOfClass:[SHSetupDataModel class] forKey:@"setupData"]; // <---- This is nil. Why?
}
// [...]
}
}
Can anyone please help me why this is returning nil? Or lead me towards a more effective debugging?
The data model itself contained a NSDictionary that was not properly decoded. The solution was to analyze the outError and then step by step work through initWithCoder methods. Finally I had to pass multiple classes in decodeObjectWithClasses:ofKey: