Сохранение пользовательских объектов - PullRequest
10 голосов
/ 15 марта 2009

У меня есть пользовательский объект, который просто наследуется от NSObject. Он имеет 3 члена - два поплавка и NSDate.

Мое приложение будет иметь массив с множеством этих объектов, и мне нужно сохранить его между запусками. Как мне это сделать?

Я думал об использовании базы данных SQLite, но думаю, что это немного излишне, поскольку единственный запрос, который я когда-либо делал, был бы select *.

В идеальном мире я хотел бы использовать файл xml plist. Я не уверен, смогу ли я сделать это с моим пользовательским объектом, хотя. Я знаю, что есть набор объектов списка свойств, и к этому относится NSArray, но writeToFile:atomically: работает только с объектами списка свойств.

Любые мысли будут оценены, спасибо!

Ответы [ 2 ]

21 голосов
/ 15 марта 2009

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, вам нужно изменить два последних метода для вашего случая, но большая часть стандартного кода будет такой же.

0 голосов
/ 15 марта 2009

Если вы хотите получить подмножество объектов, SQLite - ваш лучший выбор.

Если нет, это выбор между форматом plist и NSCoding. plist требует, чтобы вы были в состоянии преобразовать ваши пользовательские объекты во что-то удобное для plist, а затем преобразовать plist обратно в ваши объекты, но NSCoding немного сложнее, чтобы обернуть вашу голову и не может быть легко отредактирован (или проверен) вручную .

...