NSKeyedArchiver失败了CLLocationCoordinate2D结构。为什么?

时间:2012-09-05 23:52:25

标签: objective-c ios nskeyedarchiver

我不明白为什么我可以归档CGPoint结构但不归档CLLocationCoordinate2D结构。归档者有什么不同?

平台是iOS。我正在模拟器中运行,并没有尝试过该设备。

// why does this work:
NSMutableArray *points = [[[NSMutableArray alloc] init] autorelease];
CGPoint p = CGPointMake(10, 11);
[points addObject:[NSValue valueWithBytes: &p objCType: @encode(CGPoint)]];
[NSKeyedArchiver archiveRootObject:points toFile: @"/Volumes/Macintosh HD 2/points.bin" ];

// and this doesnt work:
NSMutableArray *coords = [[[NSMutableArray alloc] init] autorelease];
CLLocationCoordinate2D c = CLLocationCoordinate2DMake(121, 41);
[coords addObject:[NSValue valueWithBytes: &c objCType: @encode(CLLocationCoordinate2D)]];
[NSKeyedArchiver archiveRootObject:coords toFile: @"/Volumes/Macintosh HD 2/coords.bin" ];

我在第二个archiveRootObject发生了崩溃,并且此消息将打印到控制台:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '*** -[NSKeyedArchiver encodeValueOfObjCType:at:]: this archiver cannot encode structs'

3 个答案:

答案 0 :(得分:18)

好的,汤姆,你准备好迎接一些极客吗?在这个年轻的鞭挞者的世界里,我是一个“年长”的家伙。但是,我记得有关C的一些事情,我只是一个内心的怪人。

无论如何,这之间有一个微妙的区别:

typedef struct { double d1, d2; } Foo1;

和此:

typedef struct Foo2 { double d1, d2; } Foo2;

第一个是匿名结构的类型别名。第二个是struct Foo2的类型别名。

现在,@encode的文档说明了以下内容:

typedef struct example {
    id   anObject;
    char *aString;
    int  anInt;
} Example;

将导致{example=@*i}@encode(example) @encode(Example)。因此,这意味着@encode正在使用实际的struct标记。对于为匿名结构创建别名的typedef,看起来@encode始终返回?'

检查出来:

NSLog(@"Foo1: %s", @encode(Foo1));
NSLog(@"Foo2: %s", @encode(Foo2));

无论如何,你能猜出CLLocationCoordinate2D是如何定义的吗?是的。你猜对了。

typedef struct {
CLLocationDegrees latitude;
CLLocationDegrees longitude;
} CLLocationCoordinate2D;

我认为您应该就此提交错误报告。 @encode被破坏是因为它没有对匿名结构使用别名typedef,或者CLLocationCoordinate2D需要完全类型化,因此它不是匿名结构。

答案 1 :(得分:3)

要解决此限制,直到修复错误,只需分解坐标并重建:

- (void)encodeWithCoder:(NSCoder *)coder
{
    NSNumber *latitude = [NSNumber numberWithDouble:self.coordinate.latitude];
    NSNumber *longitude = [NSNumber numberWithDouble:self.coordinate.longitude];
    [coder encodeObject:latitude forKey:@"latitude"];
    [coder encodeObject:longitude forKey:@"longitude"];
    ...

- (id)initWithCoder:(NSCoder *)decoder
{
    CLLocationDegrees latitude = (CLLocationDegrees)[(NSNumber*)[decoder decodeObjectForKey:@"latitude"] doubleValue];
    CLLocationDegrees longitude = (CLLocationDegrees)[(NSNumber*)[decoder decodeObjectForKey:@"longitude"] doubleValue];
    CLLocationCoordinate2D coordinate = (CLLocationCoordinate2D) { latitude, longitude };
    ...

答案 2 :(得分:0)

这是因为CLLocationCoordinate2D上的@encode窒息

NSLog(@"coords %@; type: %s", coords, @encode(CLLocationCoordinate2D));收益coords ( "<00000000 00405e40 00000000 00804440>" ); type: {?=dd}