9

我不明白为什么我可以存档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" ];

我在 2 日发生崩溃archiveRootObject,此消息被打印到控制台:

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

3 回答 3

19

好的,汤姆,你准备好迎接极客了吗?在这个年轻的whippersnappers世界里,我是一个“老”的人。然而,我记得一些关于 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是因为它不使用匿名结构的别名类型定义而被破坏,要么是 CLLocationCoordinate2D 需要完全类型化,因此它不是匿名结构。

于 2012-09-06T02:04:17.310 回答
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 };
    ...
于 2013-08-25T10:26:16.793 回答
0

这是因为@encodeCLLocationCoordinate2D 阻塞

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

于 2012-09-06T00:09:06.927 回答