如何在Coredata中使用struct存储自定义对象

7
我需要将一个自定义类对象存储到Coredata中,但问题是我的自定义类包含结构体、枚举等。我尝试了以下方法:

-(void)encodeWithCoder:(NSCoder *)encoder .

但是我遇到了这个错误:

[NSKeyedArchiver encodeValueOfObjCType:at:]: this archiver cannot encode structs'

请问在Coredata中存储此对象的最佳实践是什么?请帮助我。
3个回答

6
你可以将结构体包裹在NSData中,例如:
使用归档进行编码。
[coder encodeObject:[NSData dataWithBytes:&my_struct length:sizeof(my_struct)] 
             forKey:@"my_struct"];

并使用压缩程序进行解码

NSData *data = [coder decodeObjectForKey:@"my_struct"];
[data getBytes:&my_struct length:sizeof(my_struct)];

使用 dataWithBytes:length: 在不同的大小端或32/64位平台之间是不可移植的。使用它将导致您的数据被固定在给定的设备上,用户将无法升级到不同的平台或在与创建文件的平台不同的平台上传输/打开该文件。 - Brent Priddy
@Brent 当然可以...但问题是关于iPhone,我认为这个方法在未来几年内应该能正常工作...如果苹果更换硬件,我相信他们会有一个时期使用模拟器尽可能多地移植软件...(b)程序将需要重新编译,并且可以在那时进行修复(如果需要的话)...这只是一个问题,涉及到在一种类型的硬件上创建/存储的“数据”,然后转移到新的不同架构上。 - epatel
@epatel 我有客户使用 PPC 和 Intel 将 CoreData 备份文件传输到/从 iPhone。如果我听从这个建议,我会感到头痛的。你可以为 iPhone 构建 ARM 6/7 代码,未来想象成 32/64 位的 fat binaries 也不是什么难事。这是一条“要小心”的评论,我推荐下面提到的 NSCoder 方法,它不仅在短期内安全而且永远安全。 - Brent Priddy
@Brent 我明白你的意思。但是,问题被表述为一个iPhone特定的问题,作为一个在多个平台上开发的开发者,我并不认为这是一个主要的问题。如果你不确定它会被使用,为什么要投资开发和测试呢?我们正在处理的项目使用旧的保存数据作为事实标准格式,在必要时进行适当的对齐和交换,并且我们有工具来处理这些问题。作为顾问,我的客户并不想为“可能”需要的“将来”东西付费。我认为这也是敏捷开发的基石之一。 - epatel
@Brent...今天我通常会争辩要在所有保存的文件中添加格式版本字段/条目,以便能够识别不同版本之间的不同格式。对于 plist 来说,这非常容易,只需为某个版本键设置一个字符串。有了这个,人们将始终有可能在需要时进行任何适当的转换。 - epatel
@epatel 这是一个关于版本字段的有用建议。 @Sijo 另一个有用的建议:确保你的结构体只包含基本类型(没有STL类),同时也要确保你的结构体没有指针...哦,还要确保sizeof(my_struct)没有改变(布尔型的sizeof可能会因编译器和编译器设置而改变,枚举类型的sizeof也不是固定的)。确保你不要重新排序你的结构体或任何包含在你的结构体中的结构体...我想这种方法让你想到了注意事项。我提出这个建议是因为我曾经做过这件事,不希望再次重蹈覆辙。 - Brent Priddy

4
在您的自定义类中,应该有一个NSCoding协议的自定义实现。在您自己的 - [initWithCoder:] - [encodeWithCoder:] 实现中,您可以以任何方式编码/解码结构对象。
其中一种方法是在 - [encodeWithCoder:] 中调用 [coder encodeObject:[NSValue valueWithBytes:&yourStructVariable objCType:@ encode(struct YourStructName)] forKey:“someKey”] ,并在 - [initWithCoder:] 中执行相应的解码。
然后,您可以将类对象存储为Core Data中的可转换对象。

1
使用 NSValue valueWithBytes 是导致 OP 提到的异常的原因。 - Andrew Theis

1

关于结构体,我认为最好创建一个函数来编码和解码结构体,就像任何 Objective-C 对象一样。

对于枚举,我不太确定。枚举只是与名称相关联的数字,因此只需将它们编码和解码为数字即可。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接