8

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:]: このアーカイバは構造体をエンコードできません'

この問題の解決策は、個々の double を 4 つの個別のキーにエンコードすることであることを理解しています。

私の質問は、なぜこれが起こるのかです。AnNSValueはオブジェクトなので、「このアーカイバは構造体をエンコードできません」と表示されるのはなぜですか

4

3 に答える 3

4

NSKeyedArchiverクラスのドキュメントによると、

キー付きアーカイブは、アーカイブにエンコードされたすべてのオブジェクトと値に名前またはキーが与えられるという点で、キー付きアーカイブとは異なります。

a の要素をアーカイブstructしてそれらにキーを与えるには、a の各フィールドがどこにあるか、およびこれらのフィールドの名前NSKeyedArchiverを知るためのメタデータが必要です。stored withはstructのレイアウトに関する十分な情報を提供しますが、各フィールドの名前に関する情報は欠落しています。@encodeNSValuestruct

にはフィールドの名前に関するメタデータがないstructため、適切なアーカイブ解除を保証するような方法でデータをアーカイブすることは不可能です。これが、 C が埋め込まれた s のNSKeyedArchiverアーカイブを must が拒否する理由です。NSValuestruct

于 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 に答える