Почему NSUserDefaults не удалось сохранить NSMutableDictionary в iPhone SDK?

Я хотел бы сохранить объект NSUserDefaults в NSUserDefaults . Ключевым типом в NSMutableDictionary является NSString , тип значения – NSArray , который содержит список объектов, реализующих NSCoding . В NSArray документе NSString и NSArray соответствуют NSCoding .

Я получаю эту ошибку:

[NSUserDefaults setObject: forKey:]: Попытка вставить значение non-property …. classа NSCFDictionary.

Любое решение для этого?

Я обнаружил одну альтернативу, прежде чем сохранять, я кодирую корневой объект (объект NSArray ) с помощью NSKeyedArchiver , который заканчивается NSData . Затем используйте UserDefaults, чтобы сохранить NSData .

Когда мне нужны данные, я зачитываю NSData и использую NSKeyedUnarchiver для преобразования NSData обратно в объект.

Это немного громоздко, потому что мне нужно каждый раз конвертировать в / из NSData , но он просто работает.

Вот один пример для запроса:

Сохранить:

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSMutableArray *arr = ... ; // set value NSData *data = [NSKeyedArchiver archivedDataWithRootObject:arr]; [defaults setObject:data forKey:@"theKey"]; [defaults synchronize]; 

Нагрузка:

 NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; NSData *data = [defaults objectForKey:@"theKey"]; NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data]; 

Элемент массива реализует

 @interface CommentItem : NSObject { NSString *value; } 

Затем в реализации CommentItem предусмотрены два метода:

 -(void)encodeWithCoder:(NSCoder *)encoder { [encoder encodeObject:value forKey:@"Value"]; } -(id)initWithCoder:(NSCoder *)decoder { self.value = [decoder decodeObjectForKey:@"Value"]; return self; } 

У кого-то есть лучшее решение?

Всем спасибо.

Если вы сохраняете объект в настройках пользователя по умолчанию, все объекты, рекурсивно, полностью вниз, должны быть объектами списка свойств. В соответствии с NSCoding это ничего не значит – NSUserDefaults не будет автоматически кодировать их в NSData , вы должны сделать это сами. Если ваш «список объектов, реализующих NSCoding » означает объекты, которые не являются объектами списка свойств, тогда вам нужно будет что-то сделать с ними перед сохранением по умолчанию.

FYI classы classов NSDictionaryNSDictionary , NSArray , NSString , NSDate , NSData и NSNumber . Вы можете записывать изменяемые подclassы (например, NSMutableDictionary ) в пользовательские настройки, но объекты, которые вы зачитали, всегда будут неизменными.

Все ваши ключи в словаре NSString ? Я думаю, что они должны быть, чтобы сохранить словарь в списке свойств.

Простой ответ:

NSDictionary – это только объект NSDictionary , если ключи являются NSStrings . Итак, stringWithFormat «ключ» как NSString с помощью stringWithFormat .


Решение :

 NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]]; 

Выгоды :

  1. Он добавит String-Value .
  2. Он добавит пустое значение, когда значение Value Variable равно NULL .

Рассматривали ли вы вопрос об NSCoding протокола NSCoding ? Это позволит вам кодировать и декодировать iPhone с помощью двух простых методов, которые реализуются с помощью NSCoding . Сначала вам нужно добавить NSCoding в свой class.

Вот пример:

Это файл .h

 @interface GameContent : NSObject  

Затем вам нужно будет реализовать два метода протокола NSCoding.

  - (id) initWithCoder: (NSCoder *)coder { if (self = [super init]) { [self setFoundHotSpots:[coder decodeObjectForKey:@"foundHotSpots"]]; } return self; } - (void) encodeWithCoder: (NSCoder *)coder { [coder encodeObject:foundHotSpots forKey:@"foundHotSpots"]; } 

Ознакомьтесь с документацией по NSCoder для получения дополнительной информации. Это очень удобно для моих проектов, где мне нужно сохранить состояние приложения на iPhone, если приложение закрыто и восстановить его обратно в его состояние, когда оно снова включено.

Ключ должен добавить протокол к интерфейсу, а затем реализовать два метода, которые являются частью NSCoding .

Надеюсь, это поможет!

Нет лучшего решения. Другой вариант – просто сохранить закодированный объект на диск, но это то же самое. Оба они заканчиваются NSData, который декодируется, когда вы хотите его вернуть.

  • Разбор даты JSON на IPhone
  • Использование iPhone - dequeueReusableCellWithIdentifier
  • Лучший способ удалить из NSMutableArray во время итерации?
  • Как resize UIModalPresentationFormSheet?
  • Как масштабировать UIImageView пропорционально?
  • Формат NSDate, выводящий неверную дату
  • Возвратитесь к поведению приложения после разговора по телефону в собственном коде, чем UIWebView
  • Запустите NSRunLoop в командной строке программы Cocoa
  • Использование аутентификации AFNetworking и HTTP
  • UIPopoverPresentationController на iOS 8 iPhone
  • Сохранить фотографии в пользовательский альбом в iPhones Photo Library
  • Interesting Posts

    Является ли структура агрегации Mongodb быстрее, чем карта / сокращение?

    как вернуться к предыдущему fragmentу при нажатии кнопки возврата вручную отдельного fragmentа?

    Как сохранить цвет фона и стили границы ячейки таблицы (OO.Org Writer)?

    Как работают SETLOCAL и ENABLEDELAYEDEXPANSION?

    jQuery Sortable – drag and drop нескольких элементов

    Могу ли я фильтровать и сортировать идентификаторы электронной почты в блокноте ++ и других текстовых редакторах?

    Зарегистрировать class приложения в манифесте?

    Передача массива строк в web-метод с переменным числом аргументов с использованием jQuery AJAX

    Что произойдет, если я не вызову Dispose на объекте пера?

    В чем разница между «экраном» и «единственным экраном» в мультимедийных запросах?

    Как я могу заставить сжатие gzip в IIS7 работать?

    Установить путь сборки в Eclipse для программы ndk

    CSS: маржа-верх, когда у родителя нет границы

    Есть ли подсказка компилятора для GCC, чтобы заставить предсказание ветвей всегда идти определенным образом?

    Переключить режим самолета в Android

    Давайте будем гением компьютера.