在核心数据中序列化“int”数组

时间:2011-06-17 19:25:54

标签: iphone ios core-data

我正在尝试为我正在处理的新应用程序设计数据结构,并且我正在使用核心数据(第一次)。

我一直在努力解决核心数据中缺少数组的问题,但我大部分时间都在解决这个问题。

我留下的一个问题是我的一个对象类型有一个“int”数组。我可能有很多这些整数,所以我希望它们具有空间效率。我也希望能够快速访问它们。

在我的特定情况下,我的int数组将只对它们执行两个操作。一种是迭代它们,第二种是添加新的int。最常见的操作(以及我需要保持最高效的操作)只是能够读取数组中的所有值。

对于存储,我认为我需要在我的对象上使用“二进制数据”属性。现在我想弄清楚将“int”打包成一个字节数组的最佳方法。

我的应用程序将创建目前仅在iOS设备上使用的数据,但未来可能会在其他计算机上使用,因此我想确保我的解决方案与架构无关,但同时也是最快的在具有较慢处理器且关注电池寿命的iOS设备上。

我正在考虑设计我的二进制数据,以便以“小端”格式存储整数。我的对象将是NSManagedObject的子类,它将有一个side字段(不是核心数据存储的一部分),它是一个“int *”指针,我将用它来迭代这些值。

当我的对象出现故障时,我会初始化c数组。如果endianness是“little endian”(我将使用CFByteOrderGetCurrent()确定),那么我可以使用以下代码非常有效地读取int数组:

@property (retain) NSData *data; // Core Data binary attribute
...
int *cArray = (int *) [self.data bytes];

如果字节序不是小端,我需要分配本地存储,正确解压缩int值,并使二进制属性和c-array保持最新状态。

我会在我的子类中添加代码来管理错误(例如,当出现故障时将cArray清零,并在出现故障时正确设置它。)

所以,我认为我有一个适合我的解决方案,虽然我不喜欢它。

如果有人能想出更好的方法来做我想做的事情,我会非常感激。

此外,如果有人能够想到为什么c-array和NSData之间的交互或核心数据可能会给我带来问题,我会非常感激。

谢谢, 罗恩

2 个答案:

答案 0 :(得分:2)

在CoreData中执行此操作的典型方法是与对象建立一对多关系,该对象只有一个字段来保存int值。既然你说你将拥有很多这些int值,这很可能不会是一个令人满意的解决方案。

您还需要谨慎使用CoreData实体上的二进制类型,因为如果您的二进制数据足够大,这通常会导致一些与性能相关的不良问题。

如果这些选项都不可行,您可能需要考虑从CoreData下载到较低级别的存储机制,该机制使用更传统的数据库方法,并且能够在int值上有效地执行所有所需的功能。

答案 1 :(得分:1)

C标准允许有很多有趣的事情:

  • 奇数字节(9是传统的)
  • 有符号数字的奇数表示(例如符号幅度,补码)
  • int的奇数大小(过去常见的是16)
  • 内存表示中未使用的位

我个人使用int32_t或(最好)uint32_t而不用担心奇怪的架构。我也不打扰CFByteOrderGetCurrent(),因为字节顺序在编译时是已知的:

#include <TargetConditionals.h>

#if TARGET_RT_LITTLE_ENDIAN
  insert code here
#else
  #error "Big endian architectures not supported yet!"
#endif

我也使用const int *(因为NSData不可变)。

也可能无法保证self.data在对象变成错误之前仍然有效 - 一般规则是“如果你想要一个对象存活,保留它”。也就是说,Core Data可能会持有这些对象。

最后,为什么需要将int指针存储在对象中?我只是按需生成它:

-(const int32_t*)intArray:(size_t*)count {
  NSData * d = [[self.data copy] autorelease];
  *count = [d length]/sizeof(int32_t);
  return (const int32_t*)[d bytes];
}

复制/自动释放应该是有效的,但是用于确保即使在迭代期间设置self.data,迭代的数组也不会改变。