Pensé que sabía qué estaba causando este error, pero parece que no puedo entender qué hice mal.
Aquí está el mensaje de error completo que recibo:
Intente establecer un objeto de lista que no sea de propiedad ( "<BC_Person: 0x8f3c140>" ) como un valor NSUserDefaults para personDataArray clave
Tengo una Person
clase que creo que se ajusta al NSCoding
protocolo, donde tengo ambos métodos en mi clase de persona:
- (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;
}
En algún momento de la aplicación, se establece NSString
in BC_PersonClass
, y tengo una DataSave
clase que creo que está manejando la codificación de las propiedades en mi BC_PersonClass
. Aquí está el código que estoy usando de la DataSave
clase:
- (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];
}
Espero que sea suficiente código para darte una idea de lo que estoy tratando de hacer. Una vez más, sé que mi problema radica en cómo estoy codificando mis propiedades en mi clase BC_Person, parece que no puedo entender qué estoy haciendo mal.
¡Gracias por la ayuda!
fuente
that I think is conforming to the NSCoding protocol
es muy fácil agregar pruebas unitarias para eso, y realmente vale la pena.Respuestas:
El código que publicó intenta guardar una matriz de objetos personalizados en
NSUserDefaults
. No puedes hacer eso. Implementar losNSCoding
métodos no ayuda. Sólo se puede almacenar cosas comoNSArray
,NSDictionary
,NSString
,NSData
,NSNumber
, yNSDate
enNSUserDefaults
.Necesita convertir el objeto a
NSData
(como lo tiene en algunos de los códigos) y almacenarloNSData
enNSUserDefaults
. Incluso puede almacenar unaNSArray
deNSData
si es necesario.Cuando vuelva a leer la matriz, debe desarchivar el
NSData
para recuperar susBC_Person
objetos.Quizás quieras esto:
fuente
NSMutableArray
se extiendeNSArray
. Está perfectamente bien pasar unNSMutableArray
a cualquier método que espere unNSArray
. Tenga en cuenta que la matriz realmente almacenadaNSUserDefaults
será inmutable cuando la vuelva a leer.Me parece un desperdicio ejecutar la matriz y codificar los objetos en NSData usted mismo. Su error
BC_Person is a non-property-list object
le dice que el marco no sabe cómo serializar su objeto persona.Por lo tanto, todo lo que se necesita es garantizar que su objeto personal se ajuste a NSCoding, luego simplemente puede convertir su matriz de objetos personalizados en NSData y almacenarlos en los valores predeterminados. Aquí hay un patio de recreo:
Editar : la escritura
NSUserDefaults
en Xcode 7 no funciona, por lo que el área de juegos archivará los datos y volverá a imprimir una salida. El paso UserDefaults se incluye en caso de que se solucione en un punto posteriorY Voila, ha almacenado una matriz de objetos personalizados en NSUserDefaults
fuente
func encode(with aCoder: NSCoder)
Ahorrar:
Llegar:
Para eliminar
fuente
Solución Swift 3
Clase de utilidad simple
Clase de modelo
Como llamar
fuente
Swift- 4 Xcode 9.1
prueba este código
no puede almacenar el asignador en NSUserDefault, solo puede almacenar NSData, NSString, NSNumber, NSDate, NSArray o NSDictionary.
fuente
En primer lugar, la respuesta de rmaddy (arriba) es correcta: la implementación
NSCoding
no ayuda. Sin embargo, debe implementarNSCoding
para usarNSKeyedArchiver
y todo eso, por lo que es solo un paso más ... convertir a través deNSData
.Métodos de ejemplo
Así se puede envolver sus
NSCoding
objetos en unaNSArray
oNSDictionary
o lo que sea ...fuente
Tuve este problema al intentar guardar un diccionario en
NSUserDefaults
. Resulta que no se guardaría porque conteníaNSNull
valores. Así que simplemente copié el diccionario en un diccionario mutable, eliminé los valores nulos y luego los guardé enNSUserDefaults
En este caso, sabía qué claves podrían ser
NSNull
valores.fuente
La estructura Pref es un contenedor personalizado alrededor del objeto estándar UserDefaults.
Entonces puedes usarlo de esta manera:
fuente
if let data = UserDefaults.standard.data(forKey: keyUser) {
y por cierto, el lanzamiento deUser
a noUser
tiene sentido simplementereturn try JSONDecoder().decode(User.self, from: data)
Rápido con
@propertyWrapper
Guardar
Codable
objeto enUserDefault
Ejemplo de modelo de usuario confirmar Codificable
Cómo usarlo
fuente
fuente
Swift 5 Muy fácil
fuente