несогласованное поведение по умолчанию (NSUserDefaults) в настройках iPhone simulator по умолчанию
-
19-08-2019 - |
Вопрос
Я сталкивался с очень противоречивыми результатами при разработке приложения для iPhone и попытке сохранить настройки с помощью стандартного механизма NSUserDefaults.Я использую код почти прямо из кулинарной книги разработчика iPhone Эрики Садун (фантастическая книга, кстати), она выглядит примерно так:
(void) updateDefaults { NSMutableArray *spells = [[NSMutableArray alloc] init]; NSMutableArray *locs = [[NSMutableArray alloc] init]; for (DragView *dv in [boardView subviews]) { [spells addObject:[dv whichSpell]]; [locs addObject:NSStringFromCGRect([dv frame])]; } [[NSUserDefaults standardUserDefaults] setObject:spells forKey:@"spells"]; [[NSUserDefaults standardUserDefaults] setObject:locs forKey:@"locs"]; [[NSUserDefaults standardUserDefaults] synchronize]; [spells release]; [locs release]; }
Значения иногда сохраняются...и иногда восстанавливаются.Я не могу точно определить, что заставляет или не заставляет это работать.
Есть ли у кого-нибудь еще подобный опыт?Есть какие-нибудь предложения о том, что могло бы заставить это работать?Является ли метод синхронизации лучшим способом принудительной записи на диск и сохранения значений, или есть что-то лучше (как для производства, так и для симулятора).
Спасибо Райан
Решение
Вы должны использовать NSKeyedArchiver для сохранения ваших массивов, таких как:
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:spells] forKey:@"spells"];
[[NSUserDefaults standardUserDefaults] setObject:[NSKeyedArchiver archivedDataWithRootObject:locs] forKey:@"locs"];
[[NSUserDefaults standardUserDefaults] synchronize];
Вы также должны убедиться, что ваш класс spells реализует протокол NSCoding (encodeWithCoder:и initWithCoder:), если это пользовательский класс.Похоже, что ваши locs - это NSStrings, которые будут архивироваться просто отлично.
Вам также нужно будет сделать что-то вроде
NSData *dataRepresentingSavedSpells = [currentDefaults objectForKey:@"spells"];
if (dataRepresentingSavedSpells != nil)
{
NSArray *oldSpells = [NSKeyedUnarchiver unarchiveObjectWithData:dataRepresentingSavedSpells];
}
Чтобы загрузить старые значения из значений по умолчанию.
Я использую synchronize для записи на диск при выходе, и, по моему опыту, это было очень надежно.
Другие советы
В Mac OS X и, вероятно, также в iPhone OS база данных по умолчанию может содержать только объекты списка свойств:NSString, NSNumber, NSArray, NSDictionary и NSData.
Из вашего фрагмента кода неясно, к какому типу относится заклинание, но если это не одно из вышеперечисленных, оно не будет сохранено в базе данных по умолчанию.Ваши варианты следующие:
- Напишите метод, который преобразует ваш объект в представление plist и обратно.Другими словами, метод для создания NSDictionary из вашего объекта и другой метод для инициализации объекта с помощью NSDictionary.Вы также можете сохранить его как NSArray или NSString .
- Заставьте ваш объект реализовать протокол NSCoding, а затем используйте NSKeyedArchiver для преобразования объекта в объект NSData и NSKeyedUnarchiver для его обратного преобразования.