Guardar un NSMutableArray utilizando NSUserDefaults no funciona

Tengo esta matriz mutable llamada myWallet con su statement de properties:

@property (nonatomic, strong) NSMutableArray *myWallet; 

Este set se está llenando con tarjetas, que es un object. Creo una nueva instancia de una Tarjeta desde otro View Controller, así que utilizo un método de delegado para poder pasar esta tarjeta creada en mi View Controller, que es un View View Controller. A continuación se muestra el método de delegado

 - (void)addCardViewController:(AddCardViewController *)sender didCreateCard:(Card *)newCard { // insert a new card self.myCard = newCard; [self.myWallet addObject:self.myCard]; [self.tableView reloadData]; } 

Hasta ahora, puedo crear nuevas instancias de Card y, cuando lo hago, aparece una nueva celda de tabla en mi controller de vista inicial (Card Wallet VC).

Lo que quiero es que cuando el usuario termine de usar la aplicación, la (s) instancia (es) creada (s) de la tarjeta que creó anteriormente todavía aparece en la próxima ejecución de la aplicación. Entonces utilicé NSUserDefaults para hacer esto. El siguiente método es cómo estoy usando NSUserDefaults para save.

 - (void)saveMyWallet { NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults]; [defaults setObject:self.myWallet forKey:@"myWalletArray"]; [defaults synchronize]; NSLog(@"I am saved"); } 

Llamo a este método dentro de didSelectRowAtIndexPath. Cuando ejecuto la aplicación, luego crea una nueva instancia de una Tarjeta, haz clic en la celda de la tabla, esto aparece en mi logging.

 2012-05-04 14:51:00.900 CardWallet[24998:f803] *** -[NSUserDefaults setObject:forKey:]: Attempt to insert non-property value '("<Card: 0x6aa02f0>")' of class '__NSArrayM'. Note that dictionaries and arrays in property lists must also contain only property values. 

¿Cuál podría ser una posible razón para esto? Y puedes sugerirme maneras en que puedo hacerlo.

Gracias por adelantado.

La class de su Tarjeta también debe cumplir con el Protocolo NSCoding ya que solo puede almacenar NSData , NSString , NSArray , NSDictionary y NSNumber con NSUserDefaults . Eso significa que debe agregar dos methods a su class:

 - (void)encodeWithCoder:(NSCoder *)enCoder { [super encodeWithCoder:enCoder]; [enCoder encodeObject:instanceVariable forKey:INSTANCEVARIABLE_KEY]; // Similarly for the other instance variables. .... } - (id)initWithCoder:(NSCoder *)aDecoder { if(self = [super initWithCoder:aDecoder]) { self.instanceVariable = [aDecoder decodeObjectForKey:INSTANCEVARIABLE_KEY]; // similarly for other instance variables .... } return self; } 

Luego, cree un NSData NSKeyedArchiver antes de almacenarlo en NSUserDefaults. Me gusta esto:

  NSUserDefaults *ud = [NSUserDefaults standardUserDefaults]; NSData *yourArrayAsData = [NSKeyedArchiver archivedDataWithRootObject:yourArray]; [ud setObject:sharesAsData forKey:kA_KEY_FOR_USERDEFAULTS]; 
 @implementation Card - (void)encodeWithCoder:(NSCoder *)enCoder { [super encodeWithCoder:enCoder]; [enCoder encodeObject:self.name forKey:@"CardName"]; [enCoder encodeInt:self.pin forKey:@"CardPin"]; [enCoder encodeDouble:self.points forKey:@"CardPoints"]; } - (id)initWithCoder:(NSCoder *)aDecoder { if(self = [super initWithCoder:aDecoder]) { self.name = [aDecoder decodeObjectForKey:@"CardName"]; self.pin = [aDecoder decodeIntForKey:@"CardPin"]; self.points = [aDecoder decodeDoubleForKey:@"CardPoints"]; } return self; } @end 

Suponiendo que el nombre es del tipo NSString, el pin es del tipo NSInteger y Points es del tipo Double, puede usar el código anterior directamente en su proyecto.

Si la matriz self.myWallet contiene objects que no son objects de la list de properties, necesitará codificarlo usted mismo en NSData antes de savelos y decodificarlos al cargarlos.

Echa un vistazo a la respuesta a esa pregunta .