iphone objective-c cocoa-touch nsuserdefaults nscoding

¿Por qué NSUserDefaults no pudo guardar NSMutableDictionary en iPhone SDK?



objective-c cocoa-touch (6)

Me gustaría guardar un objeto NSUserDefaults en NSUserDefaults . El tipo de clave en NSMutableDictionary es NSString , el tipo de valor es NSArray , que contiene una lista de objetos que implementa NSCoding . Por documento, NSString y NSArray ambos se ajustan a NSCoding .

Estoy recibiendo este error:

[NSUserDefaults setObject: forKey:]: intento de insertar el valor no de propiedad .... de la clase NSCFDictionary.

¿Alguna solución para esto?


¿Están todas sus claves en el diccionario NSString s? Creo que tienen que ser para guardar el diccionario en una lista de propiedades.


¿Ha pensado en implementar el protocolo NSCoding ? Esto le permitirá codificar y decodificar en el iPhone con dos métodos simples que se implementan con NSCoding . Primero necesitaría agregar NSCoding a su clase.

Aquí hay un ejemplo:

Esto está en el archivo .h

@interface GameContent : NSObject <NSCoding>

Luego deberá implementar dos métodos del Protocolo NSCoding.

- (id) initWithCoder: (NSCoder *)coder { if (self = [super init]) { [self setFoundHotSpots:[coder decodeObjectForKey:@"foundHotSpots"]]; } return self; } - (void) encodeWithCoder: (NSCoder *)coder { [coder encodeObject:foundHotSpots forKey:@"foundHotSpots"]; }

Consulte la documentación sobre NSCoder para obtener más información. Eso ha sido realmente útil para mis proyectos, donde necesito guardar el estado de la aplicación en el iPhone si la aplicación está cerrada y restaurarla a su estado cuando esté nuevamente encendida.

La clave es agregar el protocolo a la interfaz y luego implementar los dos métodos que forman parte de NSCoding .

¡Espero que esto ayude!


Descubrí una alternativa, antes de guardar, codifico el objeto raíz (objeto NSArray ) usando NSKeyedArchiver , que termina con NSData . A continuación, use UserDefaults y guarde NSData .

Cuando necesito los datos, leo los NSData y uso NSKeyedUnarchiver para NSKeyedUnarchiver a convertir NSData en el objeto.

Es un poco engorroso, porque necesito convertir a / de NSData cada vez, pero simplemente funciona.

Aquí hay un ejemplo por solicitud:

Salvar:

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

Carga:

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

El elemento en la matriz implementa

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

Luego, en la implementación de CommentItem , proporciona dos métodos:

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

Alguien tiene una mejor solución?

Gracias a todos.


No hay mejor solución. Otra opción sería simplemente guardar el objeto codificado en el disco, pero eso es lo mismo. Ambos terminan con NSData que se decodifica cuando lo desea de nuevo.


Si está guardando un objeto en los valores predeterminados del usuario, todos los objetos, recursivamente, hasta el fondo, deben ser objetos de la lista de propiedades. La conformidad con NSCoding no significa nada aquí. NSUserDefaults no los codificará automáticamente en NSData , debe hacerlo usted mismo. Si su "lista de objetos que implementa NSCoding " significa objetos que no son objetos de lista de propiedades, entonces deberá hacer algo con ellos antes de guardarlos en los valores predeterminados del usuario.

Para su información, las clases de la lista de propiedades son NSDictionary , NSArray , NSString , NSDate , NSData y NSNumber . Puede escribir subclases mutables (como NSMutableDictionary ) según las preferencias del usuario, pero los objetos que lee siempre serán inmutables.


La respuesta más simple:

NSDictionary es solo un objeto plist , si las claves son NSStrings . Por lo tanto, almacene la "clave" como NSString con stringWithFormat .

Solución:

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

Beneficios:

  1. Agregará valor de cadena .
  2. Agregará Empty-Value cuando su valor de variable sea NULL .