Question

Je souhaite enregistrer un objet NSMutableDictionary dans NSUserDefaults . Le type de clé dans NSMutableDictionary est NSString , le type de valeur est NSArray , qui contient une liste d'objets qui implémente NSCoding Par document, NSString et NSArray sont tous deux conformes à NSCoding .

Je reçois cette erreur:

  

[NSUserDefaults setObject: forKey:]: Tentative d'insérer une valeur autre que la propriété .... de la classe NSCFDictionary.

Était-ce utile?

La solution

J'ai découvert une alternative. Avant de sauvegarder, je codais l'objet racine (objet NSArray ) à l'aide de NSKeyedArchiver , qui se termine par NSData . Ensuite, utilisez UserDefaults et enregistrez le NSData .

Lorsque j'ai besoin des données, je lis le NSData et utilise NSKeyedUnarchiver pour reconvertir NSData en objet.

C’est un peu fastidieux, car j’ai besoin de convertir à / de NSData à chaque fois, mais cela fonctionne.

Voici un exemple par demande:

Enregistrer:

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

Charger:

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

L'élément du tableau implémente

@interface CommentItem : NSObject<NSCoding> {
    NSString *value;
}

Ensuite, dans l'implémentation de CommentItem , fournit deux méthodes:

-(void)encodeWithCoder:(NSCoder *)encoder
{
    [encoder encodeObject:value forKey:@"Value"];
}

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

Quelqu'un a la meilleure solution?

Merci à tous.

Autres conseils

Si vous enregistrez un objet dans les paramètres utilisateur par défaut, tous les objets, de manière récursive, doivent être des objets de liste de propriétés. Se conformer à NSCoding ne veut rien dire ici - NSUserDefaults ne les encodera pas automatiquement dans NSData , vous devez le faire vous-même. Si votre " liste d'objets qui implémente NSCoding " signifie que les objets ne sont pas des objets de liste de propriétés, vous devrez alors faire quelque chose avec eux avant de sauvegarder les valeurs par défaut de l'utilisateur.

Pour info, les classes de la liste de propriétés sont NSDictionary , NSArray , NSString , NSDate , NSData et NSNumber . Vous pouvez écrire des sous-classes mutables (telles que NSMutableDictionary ) dans les préférences utilisateur, mais les objets que vous lisez seront toujours immuables.

Toutes vos clés sont-elles dans le dictionnaire NSString ? Je pense qu'ils doivent l'être pour sauvegarder le dictionnaire dans une liste de propriétés.

Réponse la plus simple:

NSDictionary n'est qu'un objet Plist , si les clés sont des chaînes NSStrings . Enregistrez donc la "clé" en tant que NSString avec stringWithFormat .

Solution:

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

Avantages:

  1. Cela ajoutera une valeur de chaîne .
  2. Cela ajoutera une valeur vide lorsque votre valeur de variable sera NULL .

Avez-vous envisagé de mettre en œuvre le protocole NSCoding ? Cela vous permettra d’encoder et de décoder sur l’iPhone avec deux méthodes simples qui sont implémentées avec le NSCoding . Vous devez d’abord ajouter le NSCoding à votre classe.

Voici un exemple:

Ceci est dans le fichier .h

@interface GameContent : NSObject <NSCoding>

Ensuite, vous devrez implémenter deux méthodes du protocole 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"];
    }

Consultez la documentation sur NSCoder pour plus d'informations. Cela s’est avéré très utile pour mes projets où je dois sauvegarder l’état de l’application sur l’iPhone si l’application est fermée et la restaurer dans son état initial.

La clé consiste à ajouter le protocole à l'interface, puis à implémenter les deux méthodes qui font partie de NSCoding .

J'espère que cela aide!

Il n'y a pas de meilleure solution. Une autre option consisterait simplement à enregistrer l’objet codé sur le disque, mais c’est la même chose. Ils se retrouvent tous les deux avec NSData qui est décodé lorsque vous le souhaitez.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top