Pourquoi NSUserDefaults n’a pas pu enregistrer NSMutableDictionary dans le SDK iPhone?

Je voudrais enregistrer un object NSMutableDictionary dans NSUserDefaults . Le type de clé dans NSMutableDictionary est NSSsortingng , le type de valeur est NSArray , qui contient une liste d’objects qui implémente NSCoding . Par document, NSSsortingng et NSArray sont tous deux conformes à NSCoding .

Je reçois cette erreur:

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

Une solution pour cela?

J’ai trouvé une alternative, avant de sauvegarder, j’encode l’object racine (object NSArray ) en utilisant NSKeyedArchiver , qui se termine par NSData . Ensuite, utilisez UserDefaults enregistrer le NSData .

Lorsque j’ai besoin des données, je lis le NSData et utilise NSKeyedUnarchiver pour convertir NSData à l’object.

C’est un peu encombrant, parce que je dois convertir vers / depuis NSData chaque fois, mais ça marche.

Voici un exemple par demande:

Sauvegarder:

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

Charge:

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

L’élément dans le tableau est implémenté

 @interface CommentItem : NSObject { NSSsortingng *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 tout le monde.

Si vous enregistrez un object par défaut, tous les objects, récursivement, tout le long, doivent être des objects de liste de propriétés. Se conformer à NSCoding ne signifie rien ici – NSUserDefaults ne les NSUserDefaults pas automatiquement dans NSData , vous devez le faire vous-même. Si votre “liste d’objects qui implémente NSCoding ” signifie des objects qui ne sont pas des objects de liste de propriétés, vous devrez alors faire quelque chose avant d’enregistrer les valeurs par défaut de l’utilisateur.

FYI les classes de liste de propriétés sont NSDictionary , NSArray , NSSsortingng , NSDate , NSData et NSNumber . Vous pouvez écrire des sous-classes mutables (comme NSMutableDictionary ) dans les préférences de l’utilisateur, mais les objects que vous lisez seront toujours immuables.

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

Réponse la plus simple:

NSDictionary est uniquement un object plist , si les clés sont NSSsortingngs . Donc, stockez la “clé” en tant que NSSsortingng avec ssortingngWithFormat .


Solution :

 NSSsortingng *key = [NSSsortingng ssortingngWithFormat:@"%@",[dictionary valueForKey:@"Key"]]; 

Avantages :

  1. Il appenda Ssortingng-Value .
  2. Il appenda une valeur vide lorsque votre valeur de variable est 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 implémentées avec le NSCoding . Vous devez d’abord append le NSCoding à votre classe.

Voici un exemple:

Ceci est dans le fichier .h

 @interface GameContent : NSObject  

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 a été très utile pour mes projets où je dois enregistrer l’état de l’application sur l’iPhone si l’application est fermée et la restaurer à son état initial.

La clé est d’append le protocole à l’interface, puis d’implémenter les deux méthodes faisant partie de NSCoding .

J’espère que ça aide!

Il n’y a pas de meilleure solution. Une autre option serait de simplement enregistrer l’object codé sur le disque – mais cela fait la même chose. Ils se retrouvent tous deux avec NSData qui est décodé quand vous le souhaitez.