it-swarm.com.de

Warum konnte NSUserDefaults NSMutableDictionary in iOS nicht speichern?

Ich möchte ein NSMutableDictionary Objekt in NSUserDefaults speichern. Der Schlüsseltyp in NSMutableDictionary ist NSString, der Wertetyp ist NSArray, der eine Liste von Objekten enthält, die NSCoding implementieren. Pro Dokument entsprechen NSString und NSArray jeweils NSCoding.

Ich erhalte diesen Fehler:

[NSUserDefaults setObject: forKey:]: Es wurde versucht, einen Nicht-Eigenschaftswert der Klasse NSCFDictionary einzufügen.

145
BlueDolphin

Ich habe eine Alternative gefunden und vor dem Speichern das Stammobjekt (NSArray object) mit NSKeyedArchiver codiert, das mit NSData endet. Verwenden Sie dann UserDefaults, um das NSData zu speichern.

Wenn ich die Daten benötige, lese ich das NSData aus und verwende NSKeyedUnarchiver, um NSData zurück in das Objekt zu konvertieren.

Es ist ein wenig umständlich, weil ich jedes Mal nach/von NSData konvertieren muss, aber es funktioniert einfach.

Hier ist ein Beispiel pro Anfrage:

Speichern:

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

Belastung:

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

Das Element im Array wird implementiert

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

Stellt dann in der Implementierung von CommentItem zwei Methoden bereit:

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

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

Hat jemand eine bessere Lösung?

Vielen Dank an alle.

230
BlueDolphin

Wenn Sie ein Objekt in den Benutzervorgaben speichern, müssen alle Objekte rekursiv bis zum Ende Objekte einer Eigenschaftsliste sein. Die Anpassung an NSCoding hat hier nichts zu bedeuten - NSUserDefaults kodiert sie nicht automatisch in NSData, das müssen Sie selbst tun. Wenn Ihre "Liste der Objekte, die NSCoding implementieren" Objekte sind, die keine Objekte der Eigenschaftsliste sind, müssen Sie etwas damit tun, bevor Sie die Benutzervorgaben speichern.

Zu Ihrer Information sind die Klassen der Eigenschaftslisten NSDictionary, NSArray, NSString, NSDate, NSData und NSNumber. Sie können veränderbare Unterklassen (wie NSMutableDictionary) in Benutzereinstellungen schreiben, aber die Objekte, die Sie auslesen, sind immer unveränderlich.

105
Tom Harrington

Sind alle Ihre Schlüssel im Wörterbuch NSStrings? Ich denke, sie müssen sein, um das Wörterbuch in einer Eigenschaftsliste zu speichern.

14
Sophie Alpert

einfachste Antwort:

NSDictionary ist nur ein Plist-Objekt, wenn die Schlüssel sind NSStrings. Speichern Sie also "Key" als NSString mit stringWithFormat.


Lösung:

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

Vorteile:

  1. Es wird ein String-Wert hinzugefügt.
  2. Es wird ein Leerwert hinzugefügt, wenn Ihr Variablenwert NULL ist.
7
Bhavin

Es gibt keine bessere Lösung. Eine andere Möglichkeit wäre, das codierte Objekt einfach auf der Festplatte zu speichern - aber das macht dasselbe. Beide haben am Ende NSData, das dekodiert wird, wenn Sie es zurückhaben möchten.

0
Dan Keen