我试图对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
是一个对象,为什么它告诉我“这个归档器不能编码结构”
答案 0 :(得分:4)
根据NSKeyedArchiver
类的文档,
密钥存档与非密钥存档的不同之处在于,编码到存档中的所有对象和值都是名称或密钥。
为了归档struct
的元素并为其提供密钥NSKeyedArchiver
,需要元数据来了解struct
的每个字段的位置,以及这些字符的名称是什么领域。与@encode
一起存储的NSValue
为其提供了有关struct
布局的足够信息,但缺少有关每个字段名称的信息。
由于struct
中没有关于字段名称的元数据,因此无法以确保正确取消存档的方式存档数据。这就是为什么NSKeyedArchiver
必须拒绝存档嵌入了C NSValue
的{{1}}。
答案 1 :(得分:2)
我遇到了同样的问题,并认为最简单的解决方案就是无聊并单独编码所有值:
- (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];
}
答案 2 :(得分:1)
NSValue
用于将非对象(例如C结构,整数等)封装到objective-c对象中,但它没有提供为这些包装定义自定义归档/序列化例程的方法类型。这只是其界面的一部分。
如果你想归档一个包含结构的NSValue,你必须考虑像endianness这样的东西,并处理嵌套指针或其他类型的东西,这些类型不能简单地写成字节。使用NSValue
无法自动执行此操作。