Сохранение пользовательских объектов
-
22-07-2019 - |
Вопрос
У меня есть пользовательский объект, который просто наследуется от NSObject. У него есть 3 члена - два с плавающей точкой и NSDate
.
Мое приложение будет иметь массив с множеством этих объектов, и мне нужно сохранить его между запусками. Как я могу это сделать?
Я думал об использовании базы данных SQLite, но думаю, что это немного излишне, поскольку единственный запрос, который я когда-либо делал, был бы select *
.
В идеальном мире я хотел бы использовать xml plist-файл. Я не уверен, смогу ли я сделать это с моим пользовательским объектом, хотя. Я знаю, что есть набор объектов списка свойств, и NSArray
подпадает под это, но writeToFile: atomically:
работает только с объектами списка свойств.
Любые мысли будут оценены, спасибо!
Решение
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
, вам необходимо изменить два последних метода для вашего случая, но большая часть стандартного кода будет такой же.
Другие советы
Если вы хотите получить подмножество объектов, SQLite - ваш лучший выбор.
Если нет, это выбор между форматом plist и NSCoding. plist требует, чтобы вы были в состоянии преобразовать ваши пользовательские объекты во что-то, удобное для plist, а затем преобразовать plist обратно в ваши объекты, но NSCoding немного сложнее, чтобы обернуть вашу голову и не может быть легко отредактирован (или проверен) вручную . р>