持久化自定义对象

10

我有一个自定义对象,它简单地继承自NSObject。它有三个成员-两个浮点数和一个NSDate

我的应用程序将拥有一个包含多个此类对象的数组,并且我需要在运行之间进行持久化。如何实现这一点?

我考虑使用SQLite数据库,但我认为这可能有点过头了,因为我唯一要执行的查询是select *

在理想的情况下,我想使用XML plist文件。但我不确定是否可以使用我的自定义对象。我知道有一组属性列表对象,NSArray属于其中之一,但是writeToFile:atomically:仅适用于属性列表对象。

有任何想法都将不胜感激,谢谢!

2个回答

21

NSCoding 能够完全满足你的需求。我建议你在 Apple 文档中了解一下它,但我认为它很容易使用。你的类(以及任何子类)都需要实现 NSCoding 协议,并且你需要向你的对象添加 -encodeWithCoder:-initWithCoder: 方法。大多数常见的框架类已经实现了 NSCoding

你的类的代码将看起来像这样:

-(void) encodeWithCoder: (NSCoder*) coder {
  [coder encodeInteger: versionValue forKey: versionKey];
  [coder encodeObject: myStuff forKey: myStuffKey];
}

-(id) initWithCoder: (NSCoder*) coder {
  self = [super init];
  if ( ! self) return nil;
  myStuff = [[coder decodeObjectForKey: myStuffKey] retain];
  return self;
}

建议在编码时添加版本号,以便在将来的版本中管理归档格式的更改。

在我的类中,我添加了一个方便的方法来归档我的对象:

-(void) archiveToFile: (NSString*) path {
  NSMutableData *data = [[NSMutableData alloc] init];
  NSKeyedArchiver *archiver = [[NSKeyedArchiver alloc] initForWritingWithMutableData: data];
  [archiver encodeObject: self forKey: myArchiveKey];
  [archiver finishEncoding];
  [archiver release];
  [data writeToFile: path atomically: YES];
  [data release];
}

再加上一个用于取消归档或创建新对象的代码:

+(MyArchive*) newFromFile: (NSString*) path
            orWithMyStuff: (MyStuff*) myStuff
{
  NSData *data = [[NSData alloc] initWithContentsOfFile: path];
  NSKeyedUnarchiver *unarchiver = [[NSKeyedUnarchiver alloc] initForReadingWithData: data];
  MyArchive *myArchive = [unarchiver decodeObjectForKey: myArchiveKey];
  [unarchiver finishDecoding];

  if (myArchive) {
    [myArchive retain];
  } else {
    myArchive = [[MyArchive alloc] initWithStuff: myStuff;
  }
  [unarchiver release];
  [data release];
  return myArchive;
}

由于您的顶级对象是 NSArray,因此您需要针对您的情况修改最后两个方法,但大部分样板代码将保持不变。


那会生成一个漂亮的plist吗?我认为写出NSData只会产生序列化数据而不是plist。 - Jasarien
这将生成一个NSCoding归档文件,其中包含您的对象的保留副本,有点像nib文件(但您不能使用Interface Builder进行编辑)。您的文档中的“Cocoa档案和序列化编程指南”将对此进行解释。 - Becca Royal-Gordon
默认情况下,它会将数据归档为二进制属性列表格式,但是如果需要,可以更改为XML属性列表格式。不幸的是,由于其包含类和指针元数据以及对象数据,因此它并不真正易读。 - Don McCaughey
如果我的类包含结构体、枚举等,该怎么办?我在这里问了一个问题。请回答。https://dev59.com/ik_Ta4cB1Zd3GeqPD82q - S.P.

0

如果要检索对象的子集,SQLite 绝对是您最好的选择。

如果不需要,那就在 plist 和 NSCoding 之间做出选择。plist 需要您能够将自定义对象转换为适合 plist 的格式,然后将 plist 再转回您所需的对象;但是 NSCoding 要难理解一些,而且不能轻松地手动编辑(或检查)。


我不会使用子集。我只需要完整的列表持久化。如何将对象转换为plist友好格式?我的理解是有一组属性列表对象,就是这样。我的对象由任何不可plist化的内容组成... - Jasarien

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