145 votes

Pourquoi NSUserDefaults n'a pas réussi à enregistrer NSMutableDictionary dans le SDK iPhone?

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

J'obtiens cette erreur:

[NSUserDefaults setObject: forKey:]: Tentative d'insertion de la non-valeur de la propriété.... de classe NSCFDictionary.

Toute solution pour cela?

230voto

BlueDolphin Points 4647

J'ai trouvé une alternative, avant de l'enregistrer, j'ai coder l'objet racine (NSArray objet) à l'aide de NSKeyedArchiver, qui se termine avec NSData. Ensuite, utilisez UserDefaults enregistrer le NSData.

Quand j'ai besoin de données, j'ai lu le NSData, et l'utilisation NSKeyedUnarchiver pour convertir NSData de revenir à l'objet.

Il est un peu encombrant, parce que j'ai besoin de les convertir vers/à partir de NSData à chaque fois, mais il fonctionne, tout simplement.

Voici un exemple par la demande:

Enregistrer:

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

Charge:

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

L'élément dans le tableau met en œuvre

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

Ensuite, dans la mise en œuvre de CommentItem, dispose de 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 une meilleure solution?

Merci à tous.

105voto

Tom Harrington Points 17226

Si vous êtes à la sauvegarde d'un objet utilisateur, les valeurs par défaut, tous les objets, de manière récursive, tout en bas, doivent être des biens objets de la liste. Conforme à NSCoding ne veut rien dire ici-- NSUserDefaults ne codez automatiquement dans NSData, vous avez à faire vous-même. Si votre "liste d'objet qui implémente NSCoding" signifie que les objets qui ne sont pas des biens objets de la liste, alors vous aurez à faire quelque chose avec eux avant de les enregistrer à l'utilisateur par défaut.

Pour info la liste des propriétés de classes sont NSDictionary, NSArray, NSString, NSDate, NSData, et NSNumber. Vous pouvez écrire mutable sous-classes (comme NSMutableDictionary) les préférences de l'utilisateur, mais les objets que vous avez lu, toujours immuable.

14voto

Ben Alpert Points 30381

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

8voto

Bhavin Points 12613

Réponse La Plus Simple :

NSDictionary n'est qu'une plist de l'objet , si les touches sont NSStrings. Ainsi, le Magasin "Clé" en tant que NSString avec stringWithFormat.


Solution :

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

Avantages :

  1. Il va ajouter de la Chaîne de Valeur.
  2. Il va ajouter un Vide-Valeur lorsque votre Valeur de la Variable est - NULL.

5voto

Niels Hansen Points 1297

Avez-vous songé à la recherche à la mise en œuvre de la NSCoding Protocole? Cela vous permettra d'encoder et de décoder sur l'iPhone avec deux méthodes simples qui sont mis en œuvre avec la NSCoding. D'abord, vous devrez ajouter le NSCoding à votre Classe.

Voici un exemple:

C'est dans l' .h fichier

@interface GameContent : NSObject <NSCoding>

Ensuite, vous aurez besoin de mettre en œuvre deux méthodes de la NSCoding Protocole.

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

    - (void) encodeWithCoder: (NSCoder *)coder
    {
           [coder encodeObject:foundHotSpots forKey:@"foundHotSpots"];
    }

Consultez la documentation sur NSCoder pour plus d'informations. Qui est venu vraiment pratique pour mes projets où j'ai besoin de sauvegarder l'état de l'application sur l'iPhone si l'application est fermée et de le restaurer à son état lors de son retour sur.

La clé est d'ajouter le protocole de l'interface, puis de mettre en œuvre les deux méthodes qui font partie de NSCoding.

J'espère que cela aide!

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X