Почему я не могу закодировать NSValue в NSKeyedArchiver?
Я пытался закодировать MKMapView
центр и простираются в NSKeyedArchiver
для сохранения государства. Я нашел пару удобных новых MapKit NSValue
дополнения, valueWithMKCoordinate:
а также valueWithMKCoordinate:
, Попытка закодировать их в ключевой архиватор не удалась:
- (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];
}
Завершение работы приложения из-за необработанного исключения "NSInvalidArgumentException", причина: "-[NSKeyedArchiver encodeValueOfObjCType:at:]: этот архиватор не может кодировать структуры"
Я понимаю, что решение этой проблемы состоит в том, чтобы просто закодировать отдельные двойные числа в четыре отдельных ключа.
Мой вопрос: почему это происходит? NSValue
это объект, так почему он говорит мне "этот архиватор не может кодировать структуры"
3 ответа
Согласно документации NSKeyedArchiver
учебный класс,
Архив с ключами отличается от архива без ключей тем, что всем объектам и значениям, закодированным в архиве, присваиваются имена или ключи.
Для того, чтобы заархивировать элементы struct
и дать им ключи NSKeyedArchiver
потребуется метаданные, чтобы знать, где каждое поле struct
находится, и как называются эти поля. @encode
хранится с NSValue
дает достаточно информации о макете struct
, но информация об именах каждого поля отсутствует.
Поскольку нет метаданных об именах полей в struct
, было бы невозможно заархивировать данные таким образом, чтобы обеспечить надлежащее де-архивирование. Поэтому NSKeyedArchiver
должен отказаться от архива NSValue
со встроенным C struct
s.
NSValue
используется для инкапсуляции необъектного объекта (например, структур C, целых и т. д.) в объект target-c, но он не обеспечивает способ определения пользовательских процедур архивирования / сериализации для этих упакованных типов. Это просто не является частью его интерфейса.
Если вы хотите заархивировать NSValue, содержащее структуру, вам придется принять во внимание такие вещи, как порядок байтов и обращаться с такими вещами, как вложенные указатели или другие типы, которые не могут быть тривиально записаны как байты. Там нет никакого способа сделать это автоматически с NSValue
,
Я столкнулся с той же проблемой и решил, что самым простым решением будет просто скучно и кодировать все значения по отдельности:
- (void)encodeRestorableStateWithCoder:(NSCoder *)coder
{
MKCoordinateRegion region = [self.mapView region];
[coder encodeDouble:region.center.latitude forKey:RWSMapCenterLatitude];
[coder encodeDouble:region.center.longitude forKey:RWSMapCenterLongitude];
[coder encodeDouble:region.span.latitudeDelta forKey:RWSMapCenterLatitudeDelta];
[coder encodeDouble:region.span.longitudeDelta forKey:RWSMapCenterLongitudeDelta];
[super encodeRestorableStateWithCoder:coder];
}
- (void)decodeRestorableStateWithCoder:(NSCoder *)coder
{
MKCoordinateRegion region;
CLLocationCoordinate2D center;
center.latitude = [coder decodeDoubleForKey:RWSMapCenterLatitude];
center.longitude = [coder decodeDoubleForKey:RWSMapCenterLongitude];
region.center = center;
MKCoordinateSpan span;
span.latitudeDelta = [coder decodeDoubleForKey:RWSMapCenterLatitudeDelta];
span.longitudeDelta = [coder decodeDoubleForKey:RWSMapCenterLongitudeDelta];
region.span = span;
self.mapView.region = region;
[super decodeRestorableStateWithCoder:coder];
}