8

我试图将一个MKMapView中心和跨度编码为一个NSKeyedArchiver状态保存。我发现了一些方便的新 MapKitNSValue添加,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:]:此归档器无法编码结构”

我知道这个问题的解决方案是将单个双打编码为四个单独的键。

我的问题是为什么会发生这种情况。AnNSValue是一个对象,为什么它告诉我“这个归档器不能编码结构”

4

3 回答 3

4

根据NSKeyedArchiver课程的文档,

键控存档与非键控存档的不同之处在于,编码到存档中的所有对象和值都是给定的名称或键。

为了归档 a 的元素struct并为其提供密钥,NSKeyedArchiver需要元数据来了解 a 的每个字段的struct位置以及这些字段的名称。@encode存储的 with为NSValue它提供了有关 a 布局的足够信息struct,但缺少有关每个字段名称的信息。

由于没有关于 a 中字段名称的元数据struct,因此不可能以确保正确取消归档的方式归档数据。这就是为什么NSKeyedArchiver必须拒绝NSValue用嵌入的 C归档structs。

于 2013-08-28T10:22:26.743 回答
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];
}
于 2014-02-27T12:50:17.577 回答
1

NSValue用于将非对象(例如 C 结构、整数等)封装到 Objective-C 对象中,但它不提供为这些包装类型定义自定义归档/序列化例程的方法。这不是其界面的一部分。

如果你想归档一个包含结构的 NSValue,你必须考虑字节序之类的事情,并处理嵌套指针或其他不能简单地写成字节的类型。没有办法自动使用NSValue.

于 2013-08-28T10:19:57.347 回答