I was trying to encode an MKMapView center and span into an NSKeyedArchiver for state preservation. I found a couple of handy new MapKit NSValue additions, valueWithMKCoordinate: and valueWithMKCoordinate:. Trying to encode these into the keyed archiver failed:
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
NSValue *mapCenterValue = [NSValue valueWithMKCoordinate:mapView.centerCoordinate];
NSValue *mapSpanValue = [NSValue valueWithMKCoordinateSpan:mapView.region.span];
[coder encodeObject:mapCenterValue forKey:kMapCenter];
[coder encodeObject:mapSpanValue forKey:kMapSpan];
}
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSKeyedArchiver encodeValueOfObjCType:at:]: this archiver cannot encode structs'
I understand that the solution to this problem is to just encode the individual doubles into four separate keys.
My question is why does this happen. An NSValue is an object, so why is it telling me "this archiver cannot encode structs"
According to the documentation of the
NSKeyedArchiverclass,In order to archive elements of a
structand give keys to themNSKeyedArchiverwould need metadata to know where each field of astructis located, and what are the names of these fields. The@encodestored withNSValuegives it enough information about the layout of astruct, but the information about the names of each field is missing.Since there is no metadata about the names of the fields in a
struct, it would be impossible to archive the data in such a way as to ensure proper un-archiving. That is whyNSKeyedArchivermust refuse to archiveNSValues with embedded Cstructs.