I have a custom class that conforms to NSSecureCoding
. I'm trying to encode its data, write it to a file, and decode it. The class contains an int
array which I convert to an NSArray
filled with NSNumber
elements before encoding. When I decode the array, decodeObjectForKey
returns nil
. Also, when I write the encoded array to file, the plist doesn't look right. For example, it doesn't have the "key_for_ns_array" key anywhere in its structure.
Here's a simplified version of my code:
@interface c_my_data_wrapper : NSObject <NSSecureCoding>
@property (assign, nonatomic) struct s_my_data my_data; // the array exists as an int[] in here
@end
@implementation c_my_data_wrapper
- (void)encodeWithCoder:(NSCoder *)encoder
{
NSMutableArray *ns_array= [NSMutableArray array];
int_array_to_ns_array(self.my_data.my_int_array, count, ns_array);
[encoder encodeObject:ns_array forKey:@"key_for_ns_array"];
}
- (instancetype)initWithCoder:(NSCoder *)decoder
{
self= [self init];
if (self)
{
// this returns nil
NSArray *ns_array= [decoder decodeObjectForKey:@"key_for_ns_array"];
}
return self;
}
@end
c_secure_storage_data_wrapper* g_my_data_wrapper= nil; // allocation not shown
void store_data(struct s_storage_data_secure *new_data)
{
g_my_data_wrapper.my_data= *new_data;
NSData *encoded_data=
[NSKeyedArchiver archivedDataWithRootObject:g_my_data_wrapper
requiringSecureCoding:YES
error:nil];
// then I write the encoded data to a file
}
void load_data(void)
{
NSData *decoded_data= [NSData dataWithContentsOfURL:my_url];
g_my_data_wrapper=
[NSKeyedUnarchiver unarchivedObjectOfClass:[c_my_data_wrapper class]
fromData:decoded_data
error:nil];
}
void int_array_to_ns_array(
int *int_array,
int count,
NSMutableArray *out_ns_array)
{
for (int index= 0; index < count; ++index)
{
[out_ns_array addObject:[NSNumber numberWithInt:int_array[index]]];
}
}
If you're curious about the whole int array to ns array conversion thing... it's because I prefer to write in c++. I'm not very experienced with objective-c, so I only write it when I need to bridge the gap between my game and iOS. In this case, s_my_data is a type that's shared between the two.
One problem, probably the problem, is that you claim your class is NSSecureCodeing
-compliant, but you're still calling -decodeObjectForKey:
instead of -decodeObjectOfClass:forKey:
:
NSArray *ns_array= [decoder decodeObjectForKey:@"key_for_ns_array"];
That's not secure. The whole point of NSSecureCoding
is that you tell the decoder what type you're expecting to get back, which is what -decodeObjectOfClass:forKey:
does.