NSKeyedArchiver失败并显示CLLocationCoordinate2D结构。为什么?
我不明白我为什么可以存档CGPoint
结构但不是CLLocationCoordinate2D
结构。归档人员有什么不同?NSKeyedArchiver失败并显示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'
OK,汤姆,你准备好了一些极客?我是这个年轻鞭挞者世界中的“年长”的家伙。不过,我记得关于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;
将导致{[email protected]*i}
两个@encode(example)
或@encode(Example)
。所以,这意味着@encode
正在使用实际的结构标记。在创建别名匿名结构的类型定义的情况下,它看起来像@encode
总是返回?
“
检查了这一点:
NSLog(@"Foo1: %s", @encode(Foo1));
NSLog(@"Foo2: %s", @encode(Foo2));
无论如何,你可以猜测CLLocationCoordinate2D是如何定义的?是的。你猜到了。
typedef struct {
CLLocationDegrees latitude;
CLLocationDegrees longitude;
} CLLocationCoordinate2D;
我想你应该就此提交一份错误报告。 @encode
因为它不使用匿名类型定义到匿名结构而被破坏,或者CLLocationCoordinate2D需要被完全键入,因此它不是匿名结构。
这是因为@encode
扼流圈CLLocationCoordinate2D
NSLog(@"coords %@; type: %s", coords, @encode(CLLocationCoordinate2D));
产量coords ( "<00000000 00405e40 00000000 00804440>" ); type: {?=dd}
要解决这个限制,直到错误是固定的,简单地分解坐标和重建:
- (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 };
...
谢谢;这是完美的解释!我会在我的雷达报告中引用它:) – TomSwift