Warum scheiterte NSUserDefaults NSMutableDictionary in iOS zu retten?
-
19-08-2019 - |
Frage
Ich möchte ein Objekt in NSMutableDictionary
NSUserDefaults
speichern. Der Schlüsseltyp in NSMutableDictionary
NSString
ist, ist der Wert NSArray
Typ, die eine Liste von Objekt enthält, das NSCoding
implementiert. Pro Dokument, NSString
und NSArray
beide entsprechen NSCoding
.
Ich erhalte diese Fehlermeldung:
[NSUserDefaults setObject: forKey:.]: Versuch nicht-Eigenschaftswert .... der Klasse NSCFDictionary einfügen
Lösung
fand ich eine Alternative aus, bevor speichern, ich kodieren das Wurzelobjekt (NSArray
Objekt) mit NSKeyedArchiver
, die mit NSData
endet. Dann speichern verwenden UserDefaults die NSData
.
Wenn ich die Daten benötigen, las ich die NSData
aus, und verwenden Sie NSKeyedUnarchiver
NSData
zurück zum Objekt zu konvertieren.
Es ist ein wenig umständlich, weil ich zu / von NSData
jedes Mal müssen konvertieren, 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];
Last:
NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
NSData *data = [defaults objectForKey:@"theKey"];
NSArray *arr = [NSKeyedUnarchiver unarchiveObjectWithData:data];
das Element im Array implementiert
@interface CommentItem : NSObject<NSCoding> {
NSString *value;
}
Dann bei der Umsetzung von CommentItem
, gibt es zwei Methoden:
-(void)encodeWithCoder:(NSCoder *)encoder
{
[encoder encodeObject:value forKey:@"Value"];
}
-(id)initWithCoder:(NSCoder *)decoder
{
self.value = [decoder decodeObjectForKey:@"Value"];
return self;
}
Wer hat eine bessere Lösung?
Danke an alle.
Andere Tipps
Wenn Sie ein Objekt in Benutzereinstellungen sind zu speichern, alle Objekte, rekursiv, den ganzen Weg nach unten, müssen Eigenschaftsliste Objekte sein. Konform zu NSCoding bedeutet nichts hier-- NSUserDefaults
wird nicht automatisch in NSData
kodieren, haben Sie das selbst zu tun. Wenn Ihre „Liste von Objekt, das NSCoding
implementiert“ bedeutet Objekte, die nicht Eigenschaftsliste Objekte sind, dann werden Sie etwas mit ihnen zu tun, bevor Sie Benutzereinstellungen zu speichern.
Zu Ihrer Information der Eigenschaftsliste Klassen sind NSDictionary
, NSArray
, NSString
, NSDate
, NSData
und NSNumber
. Sie können wandelbar Unterklassen schreiben (wie NSMutableDictionary
) an Benutzereinstellungen, aber die Objekte, die Sie immer unveränderlich sein wird, ausgelesen werden.
Sind alle Ihre Schlüssel im Wörterbuch NSString
s? Ich denke, sie in sein muß, um das Wörterbuch zu einer Eigenschaftsliste zu speichern.
Einfachstes Antwort:
NSDictionary
ist nur ein plist Objekt , wenn die Tasten sind NSStrings .
So speichern Sie die "Key" als NSString
mit stringWithFormat
.
Lösung:
NSString *key = [NSString stringWithFormat:@"%@",[dictionary valueForKey:@"Key"]];
Vorteile:
- Es fügt String-Wert .
- Es fügt Leer-Wert , wenn Ihr Wert der Variable ist
NULL
.
Haben Sie darüber nachgedacht, Blick auf die NSCoding
Protokoll implementieren? Dies ermöglicht Ihnen, mit zwei einfachen Methoden auf dem iPhone kodieren und dekodieren, die mit dem NSCoding
umgesetzt werden. Zunächst müssen Sie das NSCoding
zu Ihrer Klasse hinzuzufügen.
Hier ist ein Beispiel:
Dies ist in der H-Datei
@interface GameContent : NSObject <NSCoding>
Dann müssen Sie zwei Methoden des NSCoding Protokoll umzusetzen.
- (id) initWithCoder: (NSCoder *)coder
{
if (self = [super init])
{
[self setFoundHotSpots:[coder decodeObjectForKey:@"foundHotSpots"]];
}
return self;
}
- (void) encodeWithCoder: (NSCoder *)coder
{
[coder encodeObject:foundHotSpots forKey:@"foundHotSpots"];
}
Schauen Sie sich die Dokumentation auf NSCoder für weitere Informationen. Das hat sich in wirklich nützlich sein für meine Projekte, wo ich den Zustand der Anwendung auf dem iPhone zu speichern, wenn die Anwendung geschlossen ist und es wieder zurück, um es ist Zustand, wenn den Rücken.
Der Schlüssel ist, um das Protokoll zu der Schnittstelle hinzuzufügen und dann implementieren die beiden Methoden, den Teil NSCoding
sind.
Ich hoffe, das hilft!
Es gibt keine bessere Lösung. Eine andere Möglichkeit wäre, nur das codierte Objekt auf der Festplatte speichern - aber das ist das gleiche tun. Beide am Ende mit NSData, die decodiert wird, wenn Sie es wollen zurück.