Pregunta

Me gustaría guardar un objeto NSMutableDictionary 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 .

Recibo este error:

  

[NSUserDefaults setObject: forKey:]: Intenta insertar un valor que no sea de propiedad ... de la clase NSCFDictionary.

¿Fue útil?

Solución

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

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

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

Aquí hay un ejemplo por solicitud:

Guardar:

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

Cargar:

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.

Otros consejos

Si está guardando un objeto en los valores predeterminados del usuario, todos los objetos, recursivamente, hasta el final, deben ser objetos de la lista de propiedades. Cumplir 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 la lista de propiedades, entonces tendrá que 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 ) a las preferencias del usuario, pero los objetos que lee siempre serán inmutables.

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

Respuesta más simple:

NSDictionary es solo un objeto plist , si las teclas 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á Valor vacío cuando su valor de variable sea NULL .

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

Aquí hay un ejemplo:

Esto está en el archivo .h

@interface GameContent : NSObject <NSCoding>

Entonces 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 en NSCoder para obtener más información. Eso ha sido muy útil para mis proyectos en los que 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 activada.

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!

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 quieres recuperarlo.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top