NSCodificación de NSMutableDictionaries que contiene objects personalizados

Estaba intentando serializar un object SearchEntity (object personalizado) que contiene un NSMutableDictionary contiene un set de tipo CategoryEntity (object personalizado).

1 SearchEntity<NSCoding> contiene: 1 parameters NSMutableDictionary (parameters) que contienen X CategoryEntities<NSCoding> contienen solo cadenas y numbers.

En esta línea [encoder encodeObject:parameters forKey:kPreviousSearchEntityKey]; en SearchEntity encodeWithCoder "obtengo GDB: interrumpido cada vez, sin post de error, exception, etc. solo GDB: interrumpido.

Esta es la implementación en SearchEntity y los parameters son los NSMutableDictionary

 #pragma mark - #pragma mark NSCoding delegate methods - (void) encodeWithCoder:(NSCoder*)encoder { //encode all the values so they can be persisted in NSUserdefaults if (parameters) [encoder encodeObject:parameters forKey:kPreviousSearchEntityKey]; //GDB:Interrupted! } - (id) initWithCoder:(NSCoder*)decoder { if (self = [super init]) { //decode all values to return an object from NSUserdefaults in the same state as when saved [self setParameters:[decoder decodeObjectForKey:kPreviousSearchEntityKey]]; } return self; } 

The CategoryEntity también implementa el protocolo NSCoding y se ve así:

 - (void) encodeWithCoder:(NSCoder*)encoder { //encode all the values so they can be persisted in NSUserdefaults [encoder encodeObject:ID forKey:kIDKey]; [encoder encodeObject:text forKey:kTextKey]; [encoder encodeObject:category forKey:kCategoryKey]; [encoder encodeObject:categoryIdentifierKey forKey:kCategoryIdentifierKey]; } - (id) initWithCoder:(NSCoder*)decoder { if (self = [super init]) { //decode all values to return an object from NSUserdefaults in the same state as when saved [self setID:[decoder decodeObjectForKey:kIDKey]]; [self setText:[decoder decodeObjectForKey:kTextKey]]; [self setCategory:[decoder decodeObjectForKey:kCategoryKey]]; [self setCategoryIdentifierKey:[decoder decodeObjectForKey:kCategoryIdentifierKey]]; } return self; } 

Intento codificarlo desde un contenedor para NSUserDefaults, así:

 + (void) setPreviousSearchParameters:(SearchParameterEntity*) entity { if (entity) { //first encode the entity (implements the NSCoding protocol) then save it NSData *encodedObject = [NSKeyedArchiver archivedDataWithRootObject:entity]; [[self defaults] setObject:encodedObject forKey:kPreviousSearchKey]; [[self defaults] synchronize]; } } + (SearchParameterEntity*) getPreviousSearchParameters { //retrieve the encoded NSData object that was saved, decode and return it SearchParameterEntity *entity = nil; NSData *encodedObject = [[self defaults] objectForKey:kPreviousSearchKey]; if (encodedObject) entity = [NSKeyedUnarchiver unarchiveObjectWithData:encodedObject]; return entity; } 

Estaba pensando que cuando le pida Serialize a SearchEntity, comenzaría a serializar el object 'mutableDictionary' de los parameters, NSCoder llamará a "codificar" en las Entidades de Categoría contenidas en el dictionary y todos responderán con sus objects codificados correctos.

Sin embargo, acabo de get GDB: interrumpido en la parte inferior de la console.

¿Cómo puedo depurar esto?

¿Y mi enfoque es incorrecto, debo include todos los niveles de encoding en NSData?

PD. Hago exactamente lo mismo con una ResultEntity contiene NSArrays of CategoryEntities , codifica sin problemas, así que supongo que el NSMutableDictionary es lo único que sobresale.

El código que ha publicado no parece ser incorrecto. He adivinado algunos detalles que has omitido y obtengo un resultado exitoso de un progtwig de testing que contiene tu código con suficiente repetición para mostrar que codifica / decodifica correctamente.

(Puede comstackrlo desde la línea de command usando: gcc -framework foundation test.m -o test y ejecuta con: ./test .)

Con respecto a su pregunta, ¿cómo puedo depurar esto ? Sugiero un enfoque de la siguiente manera:

  • (Temporalmente) modifique su código para que sea lo más simple posible . Por ejemplo, puede cambiar la propiedad de parameters a un NSString simple y verificar primero que funciona correctamente.
  • Lentamente agregue complejidad, presentando una propiedad nueva a la vez , hasta que el error comience nuevamente. Eventualmente, usted se limitará a donde provienen los datos problemáticos.

Por desgracia, si esto ocurre debido a alguna memory mal administrada en otra parte de la aplicación, la debugging de este código en sí puede no llevarlo a ninguna parte. Pruebe (manualmente) verificar que la memory se administre correctamente para cada dato que recibe para la encoding.

Si ya está usando Core Data , podría considerar persistir solo la ID del object en los valores pnetworkingeterminados del usuario y restaurar el gráfico del object en function de eso. (Consulte: Archivar NSManagedObject con NSCoding ).

Le sugiero que omita primero el NSMutableArray. Deje que SearchEntity contenga solo una CategoríaEntity y vea si funciona.

El código que publicaste se ve bien, es posible que desee darnos un context más detallado.

Para la encoding de objects, este file puede ayudar: DateDetailEntry

El problema con el archivado de objects con NSKeyedArchiver es que no puede codificar objects mutables . Solo las instancias de NSArray , NSDictionary , NSString , NSDate , NSNumber y NSData (y algunas de sus subclasss) pueden ser serializadas.

Por lo tanto, en su método encodeWithCoder: debería intentar crear NSDictionary desde NSMutableDictionary y luego codificar el inmutable:

 if (parameters) { NSDictionary *dict = [NSDictionary dictionaryWithDictionary:parameters]; [encoder encodeObject:dict forKey:kPreviousSearchEntityKey]; } 

También en el método initWithCoder: intente crear NSMutableDictionary desde el inmutable codificado:

 NSDictionary *dict = [decoder decodeObjectForKey:kPreviousSearchEntityKey]; [self setParameters:[NSMutableDictionary dictionaryWithDictionary:dict]]; 

También verifique que todos los obejct dentro del dictionary de parameters ajusten al protocolo NSCoding y asegúrese de que todos ellos codifiquen solo objects inmutables en sus methods encodeWithCoder: .

Espero que resuelva el problema.