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

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

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

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

6 ответов

Решение

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

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

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

Самый простой ответ:

NSDictionary является только объектом plist, если ключи являются NSStrings. Итак, Храните "Ключ" как NSString с stringWithFormat,


Решение:

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

Выгоды:

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

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

Вот пример:

Это в.h файле

@interface GameContent : NSObject <NSCoding>

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

Другие вопросы по тегам