J'aimerais enregistrer un objet NSMutableDictionary
dans NSUserDefaults
. Le type de clé dans NSMutableDictionary
est NSString
, le type de valeur est NSArray
, qui contient la liste des objets qui implémentent 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.
J'ai découvert une alternative, avant de sauvegarder, je codais l'objet racine (NSArray
object) en utilisant NSKeyedArchiver
, qui se terminait par NSData
. Ensuite, utilisez UserDefaults et sauvegardez le NSData
.
Lorsque j'ai besoin des données, je lis le NSData
et utilise NSKeyedUnarchiver
pour convertir NSData
en objet.
C'est un peu lourd, car je dois convertir à/de NSData
à chaque fois, mais ça fonctionne.
Voici un exemple par demande:
Sauver:
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 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 une meilleure solution?
Merci tout le monde.
Si vous enregistrez un objet dans les valeurs par défaut de l'utilisateur, tous les objets, de manière récursive, jusqu'au bout, 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'objet qui implémente NSCoding
" désigne des objets qui ne sont pas des objets de liste de propriétés, vous devrez alors en faire quelque chose avant de sauvegarder les paramètres par défaut de l'utilisateur.
Pour votre information, les classes de la liste de propriétés sont NSDictionary
, NSArray
, NSString
, NSDate
, NSData
et NSNumber
. Vous pouvez écrire des sous-classes mutables (comme NSMutableDictionary
) dans les préférences de l'utilisateur, mais les objets que vous lisez seront toujours immuables.
Toutes vos clés sont-elles dans le dictionnaire NSString
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
n'est qu'un objet plist, si les clés sont NSStrings. Donc, stockez le "Key" comme NSString
avec stringWithFormat
.
Solution:
NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];
Avantages:
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:
C'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 ça aide!
Il n'y a pas de meilleure solution. Une autre option serait simplement de sauvegarder 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.