Je pensais savoir ce qui causait cette erreur, mais je n'arrive pas à comprendre ce que j'ai fait de mal.
Voici le message d'erreur complet que je reçois:
Essayez de définir un objet ne figurant pas dans la liste des propriétés ( "<BC_Person: 0x8f3c140>" ) en tant que valeur NSUserDefaults pour la clé personDataArray
J'ai une Person
classe qui je pense est conforme au NSCoding
protocole, où j'ai ces deux méthodes dans ma classe personne:
- (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;
}
À un certain moment dans l'application, le NSString
dans BC_PersonClass
est défini, et j'ai une DataSave
classe qui, je pense, gère l'encodage des propriétés dans mon BC_PersonClass
. Voici le code que j'utilise dans la DataSave
classe:
- (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];
}
J'espère que c'est assez de code pour vous donner une idée de ce que j'essaie de faire. Encore une fois, je sais que mon problème réside dans la façon dont j'encode mes propriétés dans ma classe BC_Person, je n'arrive pas à comprendre ce que je fais mal.
Merci pour l'aide!
la source
that I think is conforming to the NSCoding protocol
il est super facile d'ajouter des tests unitaires pour cela, et ça vaut vraiment le coup.Réponses:
Le code que vous avez publié tente d'enregistrer un tableau d'objets personnalisés dans
NSUserDefaults
. Tu ne peux pas faire ça. L'implémentation desNSCoding
méthodes n'aide pas. Vous ne pouvez stocker des choses commeNSArray
,NSDictionary
,NSString
,NSData
,NSNumber
etNSDate
dansNSUserDefaults
.Vous devez convertir l'objet
NSData
(comme vous l'avez fait dans certains codes) et le stockerNSData
dansNSUserDefaults
. Vous pouvez même stocker unNSArray
deNSData
si vous avez besoin.Lorsque vous relisez le tableau, vous devez désarchiver le
NSData
pour récupérer vosBC_Person
objets.Peut-être que vous voulez ceci:
la source
NSMutableArray
s'étendNSArray
. C'est parfaitement bien de passer unNSMutableArray
à n'importe quelle méthode qui attend unNSArray
. Gardez à l'esprit que le tableau réellement stocké dansNSUserDefaults
sera immuable lorsque vous le relirez.Il me semble plutôt inutile de parcourir le tableau et de coder vous-même les objets dans NSData. Votre erreur
BC_Person is a non-property-list object
vous indique que le framework ne sait pas comment sérialiser votre objet personne.Donc, tout ce qui est nécessaire est de vous assurer que votre objet personne est conforme au NSCoding, vous pouvez simplement convertir votre tableau d'objets personnalisés en NSData et le stocker en valeurs par défaut. Voici un terrain de jeu:
Modifier : L'écriture dans
NSUserDefaults
est interrompue sur Xcode 7, de sorte que le terrain de jeu archivera les données et sauvegardera et imprimera une sortie. L'étape UserDefaults est incluse au cas où elle serait corrigée ultérieurementEt voilà, vous avez stocké un tableau d'objets personnalisés dans NSUserDefaults
la source
func encode(with aCoder: NSCoder)
Sauver:
Obtenir:
Pour supprimer
la source
Solution Swift 3
Classe utilitaire simple
Classe de modèle
Comment appeler
la source
Swift- 4 Xcode 9.1
essayez ce code
vous ne pouvez pas stocker le mappeur dans NSUserDefault, vous pouvez uniquement stocker NSData, NSString, NSNumber, NSDate, NSArray ou NSDictionary.
la source
Tout d'abord, la réponse de rmaddy (ci-dessus) est correcte: l'implémentation
NSCoding
n'aide pas. Cependant, vous devez implémenterNSCoding
pour utiliserNSKeyedArchiver
et tout cela, donc ce n'est qu'une étape de plus ... la conversion viaNSData
.Exemples de méthodes
Vous pouvez donc envelopper vos
NSCoding
objets dans unNSArray
ouNSDictionary
ou autre ...la source
J'ai eu ce problème en essayant d'enregistrer un dictionnaire dans
NSUserDefaults
. Il s'avère qu'il ne serait pas enregistré car il contenait desNSNull
valeurs. Je viens donc de copier le dictionnaire dans un dictionnaire mutable supprimé les null puis enregistré dansNSUserDefaults
Dans ce cas, je savais quelles clés pouvaient être des
NSNull
valeurs.la source
La structure Pref est un wrapper personnalisé autour de l'objet standard UserDefaults.
Vous pouvez donc l'utiliser de cette façon:
la source
if let data = UserDefaults.standard.data(forKey: keyUser) {
et Btw casting deUser
toUser
est inutilereturn try JSONDecoder().decode(User.self, from: data)
Rapide avec
@propertyWrapper
Enregistrer l'
Codable
objet dansUserDefault
Exemple de modèle d'utilisateur confirmable codable
Comment l'utiliser
la source
la source
Swift 5 Très facile
la source