Ich dachte, ich wüsste, was diesen Fehler verursacht, aber ich kann nicht herausfinden, was ich falsch gemacht habe.
Hier ist die vollständige Fehlermeldung, die ich erhalte:
Versuchen Sie, ein Objekt festzulegen, das keine Eigenschaftsliste ist ( "<BC_Person: 0x8f3c140>" ) als NSUserDefaults-Wert für den Schlüssel personDataArray
Ich habe eine Person
Klasse, die meiner Meinung nach dem NSCoding
Protokoll entspricht, wobei ich beide Methoden in meiner Personenklasse habe:
- (void)encodeWithCoder:(NSCoder *)coder {
[coder encodeObject:self.personsName forKey:@"BCPersonsName"];
[coder encodeObject:self.personsBills forKey:@"BCPersonsBillsArray"];
}
- (id)initWithCoder:(NSCoder *)coder {
self = [super init];
if (self) {
self.personsName = [coder decodeObjectForKey:@"BCPersonsName"];
self.personsBills = [coder decodeObjectForKey:@"BCPersonsBillsArray"];
}
return self;
}
Irgendwann in der App ist das NSString
in BC_PersonClass
festgelegt, und ich habe eine DataSave
Klasse, die meiner Meinung nach die Codierung der Eigenschaften in meinem übernimmt BC_PersonClass
. Hier ist der Code, den ich aus der DataSave
Klasse verwende:
- (void)savePersonArrayData:(BC_Person *)personObject
{
// NSLog(@"name of the person %@", personObject.personsName);
[mutableDataArray addObject:personObject];
// set the temp array to the mutableData array
tempMuteArray = [NSMutableArray arrayWithArray:mutableDataArray];
// save the person object as nsData
NSData *personEncodedObject = [NSKeyedArchiver archivedDataWithRootObject:personObject];
// first add the person object to the mutable array
[tempMuteArray addObject:personEncodedObject];
// NSLog(@"Objects in the array %lu", (unsigned long)mutableDataArray.count);
// now we set that data array to the mutable array for saving
dataArray = [[NSArray alloc] initWithArray:mutableDataArray];
//dataArray = [NSArray arrayWithArray:mutableDataArray];
// save the object to NS User Defaults
NSUserDefaults *userData = [NSUserDefaults standardUserDefaults];
[userData setObject:dataArray forKey:@"personDataArray"];
[userData synchronize];
}
Ich hoffe, dies ist genug Code, um Ihnen eine Vorstellung davon zu geben, was ich versuche zu tun. Wieder weiß ich, dass mein Problem darin liegt, wie ich meine Eigenschaften in meiner BC_Person-Klasse codiere. Ich kann einfach nicht herausfinden, was ich falsch mache.
Danke für die Hilfe!
quelle
that I think is conforming to the NSCoding protocol
Es ist super einfach, Unit-Tests dafür hinzuzufügen, und es lohnt sich wirklich.Antworten:
Der von Ihnen veröffentlichte Code versucht, ein Array von benutzerdefinierten Objekten in zu speichern
NSUserDefaults
. Das kannst du nicht machen. Die Implementierung derNSCoding
Methoden hilft nicht. Sie können nur speichern Dinge wieNSArray
,NSDictionary
,NSString
,NSData
,NSNumber
, undNSDate
inNSUserDefaults
.Sie müssen das Objekt zu konvertieren
NSData
und zu speichern , dass (wie Sie in einem Teil des Codes haben)NSData
inNSUserDefaults
. Sie können sogar eineNSArray
von speichern,NSData
wenn Sie müssen.Wenn Sie das Array zurücklesen, müssen Sie die Archivierung aufheben
NSData
, um IhreBC_Person
Objekte zurückzubekommen.Vielleicht möchten Sie das:
quelle
NSMutableArray
erstreckt sichNSArray
. Es ist vollkommen in Ordnung, eineNSMutableArray
an eine Methode zu übergeben, die eine erwartetNSArray
. Beachten Sie, dass das tatsächlich gespeicherte Array beimNSUserDefaults
Zurücklesen unveränderlich ist.Es erscheint mir ziemlich verschwenderisch, das Array zu durchlaufen und die Objekte selbst in NSData zu kodieren. Ihr Fehler
BC_Person is a non-property-list object
sagt Ihnen, dass das Framework nicht weiß, wie Sie Ihr Personenobjekt serialisieren sollen.Sie müssen also nur sicherstellen, dass Ihr Personenobjekt der NSCoding entspricht. Anschließend können Sie einfach Ihr Array benutzerdefinierter Objekte in NSData konvertieren und diese in den Standardeinstellungen speichern. Hier ist ein Spielplatz:
Bearbeiten : Das Schreiben in
NSUserDefaults
ist auf Xcode 7 unterbrochen, sodass der Spielplatz in Daten archiviert und eine Ausgabe zurückgesendet und gedruckt wird. Der UserDefaults-Schritt ist enthalten, falls er zu einem späteren Zeitpunkt behoben wirdUnd Voila, Sie haben eine Reihe von benutzerdefinierten Objekten in NSUserDefaults gespeichert
quelle
func encode(with aCoder: NSCoder)
Speichern:
Bekommen:
Zum Entfernen
quelle
Swift 3-Lösung
Einfache Utility-Klasse
Modellklasse
Wie rufe ich an?
quelle
Swift-4 Xcode 9.1
Versuchen Sie diesen Code
Sie können Mapper nicht in NSUserDefault speichern, sondern nur NSData, NSString, NSNumber, NSDate, NSArray oder NSDictionary.
quelle
Zunächst einmal ist die Antwort von rmaddy (oben) richtig: Die Implementierung
NSCoding
hilft nicht. Sie müssen jedoch implementierenNSCoding
, umNSKeyedArchiver
und all das zu verwenden, so dass es nur noch ein Schritt ist ... Konvertieren überNSData
.Beispielmethoden
So können Sie Ihre
NSCoding
Objekte in einNSArray
oderNSDictionary
oder was auch immer einwickeln ...quelle
Ich hatte dieses Problem beim Speichern eines Wörterbuchs
NSUserDefaults
. Es stellte sich heraus, dass es nicht speichern würde, weil esNSNull
Werte enthielt . Also habe ich das Wörterbuch einfach in ein veränderliches Wörterbuch kopiert, die Nullen entfernt und dann in gespeichertNSUserDefaults
In diesem Fall wusste ich, welche Schlüssel
NSNull
Werte sein könnten .quelle
Die Pref- Struktur ist ein benutzerdefinierter Wrapper um das UserDefaults-Standardobjekt.
Sie können es also folgendermaßen verwenden:
quelle
if let data = UserDefaults.standard.data(forKey: keyUser) {
und Btw Casting vonUser
bisUser
ist nur sinnlosreturn try JSONDecoder().decode(User.self, from: data)
Schnell mit
@propertyWrapper
Codable
Objekt speichern unterUserDefault
Beispiel Benutzermodell bestätigen Codierbar
Wie man es benutzt
quelle
quelle
Swift 5 Sehr einfacher Weg
quelle