Why can't I encode an NSValue in an NSKeyedArchiver?
cocoa, mapkit, nsvalue, objective-c, uikit-state-preservation
Solution
According to the documentation of the `NSKeyedArchiver` class,
A keyed archive differs from a non-keyed archive in that all the objects and values encoded into the archive are given names, or keys.
In order to archive elements of a `struct`and give keys to them `NSKeyedArchiver` would need metadata to know where each field of a `struct` is located, and what are the names of these fields. The `@encode` stored with `NSValue` gives it enough information about the layout of a `struct`, 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 why `NSKeyedArchiver` must refuse to archive `NSValue`s with embedded C `struct`s.
Problem
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"