Objective c NSKeyedArchiver使用CLLocationCoordinate2D结构失败。为什么?

Objective c NSKeyedArchiver使用CLLocationCoordinate2D结构失败。为什么?,objective-c,ios,nskeyedarchiver,Objective C,Ios,Nskeyedarchiver,我不明白为什么我可以归档CGPointstructs,但不能归档CLLocationCoordinate2Dstructs。对档案员有什么不同 平台是iOS。我正在模拟器中运行,还没有在设备上尝试过 // why does this work: NSMutableArray *points = [[[NSMutableArray alloc] init] autorelease]; CGPoint p = CGPointMake(10, 11); [points addObject:[NSVal

我不明白为什么我可以归档
CGPoint
structs,但不能归档
CLLocationCoordinate2D
structs。对档案员有什么不同

平台是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'

这是因为
@encode
阻塞了CLLocationCoordinate2D

NSLog(@“coords%@;类型:%s”,coords,@encode(CLLocationCoordinate2D))产量<代码>协调(
""

); 键入:{?=dd}

好的,汤姆,你准备好了吗?在这个年轻的打盹儿的世界里,我是一个“年长”的家伙。然而,我记得一些关于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;
将导致
@encode(示例)
@encode(示例)
{example=@*i}
。因此,这意味着
@encode
正在使用实际的struct标记。对于为匿名结构创建别名的typedef,它看起来像
@encode
总是返回

看看这个:

NSLog(@"Foo1: %s", @encode(Foo1));
NSLog(@"Foo2: %s", @encode(Foo2));
不管怎样,你能猜出CLLocationCoordinate2D是如何定义的吗?是的。你猜对了

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

我认为你应该就此提交一份bug报告。
@encode
被破坏是因为它不使用别名typedefs来匿名结构,或者CLLocationCoordinate2D需要完全类型化,所以它不是匿名结构。

要绕过此限制直到错误被修复,只需分解坐标并重新构建:

- (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 };
    ...

好的,这很有趣。因此@encode得到的结果是,它是一个具有两个双精度的结构,但没有找到类型名。怎么会?实际上,为什么类型名对编码结构很重要呢?我认为编码会生成一个字符串,用于执行类似于
[[NSClassFromString(@encode(name))alloc]init]
或类似的黑魔法来查找生成
CLLocationCoord
NSPoint
或诸如此类的操作。谢谢;这是最好的解释!我将在我的雷达报告中引用它:)它现在被定义为:struct CLLocationCoordinate2D{CLLocationDegrees latitude;CLLocationDegrees longitude;};类型定义结构CLLocationCoordinate2D CLLocationCoordinate2D;所以我猜@encode坏了。