Swift: guardando datos de usuario usando NSKeyedArchiver, obteniendo un error en la conversión a NSArray

Entonces tengo una variedad de objects personalizados. Cuando trato de save la matriz en NSUserDefaults, tengo que archivarlos. Esto es lo que estoy haciendo para archivar la matriz de mis objects personalizados:

override func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int { //3 var allMessages = defaults.objectForKey(UserDefaultsMesssageKey) as! [AddMessageViewController.harassText] var aMessage = AddMessageViewController.harassText(phoneNumber: 0, message: "1", frequency: 1, active: 1) allMessages.append(aMessage) saveMessage(allMessages) return (allMessages.count) } func archiveMessage(message:[AddMessageViewController.harassText]) -> NSData { let archivedObject = NSKeyedArchiver.archivedDataWithRootObject(message as NSArray) return archivedObject } func saveMessage(messages: [AddMessageViewController.harassText]) { let archivedObject = archiveMessage(messages) defaults.setObject(archivedObject, forKey: UserDefaultsMesssageKey) defaults.synchronize() } func retrieveData()-> [AddMessageViewController.harassText]? { if let unarchiveObject = NSUserDefaults.standardUserDefaults().objectForKey(UserDefaultsMesssageKey) as? NSData { return NSKeyedUnarchiver.unarchiveObjectWithData(unarchiveObject) as? [AddMessageViewController.harassText] } return nil } 

El flujo es:

  1. En la llamada saveMessage, pase la matriz personalizada para get un file. A continuación, se muestra cómo se ve la matriz a GDB. Puedes ver que es una matriz y tiene 1 object de class contenido en ella.

    ([Harass_Your_Kate.AddMessageViewController.harassText]) $R0 = 1 value { [0] = 0x00007fa5ab409600 { ObjectiveC.NSObject = { isa = Harass_Your_Kate.AddMessageViewController.harassText } phoneNumber = 0 message = "1" frequency = 1 active = 1 } }

  2. La matriz se pasa a archiveMessage. El código inmediatamente falla en el método NSKeyedArchiver. El post de error es el siguiente:

     [_TtCC16Harass_Your_Kate24AddMessageViewController10harassText encodeWithCoder:]: unrecognized selector sent to instance 0x7fa5ab409600 

    2016-07-15 16: 31: 26.019 Acosar a su Kate [5858: 7847495] * – [NSKeyedArchiver dealloc]: advertencia: NSKeyedArchiver desasignado sin haber tenido -finishEncoding llamado. 2016-07-15 16: 31: 26.023 Acosar a Kate [5858: 7847495] * Terminar la aplicación debido a una exception no detectada 'NSInvalidArgumentException', motivo: '- [_TtCC16Harass_Your_Kate24AddMessageViewController10harassText encodeWithCoder:]: selector no reconocido enviado a la instancia 0x7fa5ab409600

Agradezco toda la ayuda, gracias de antemano!

EDIT: Aquí está la definición de mi object:

 class Text : NSObject { var phoneNumber = 0 //Text address to send to var message: String = "" //Message to be sent var frequency = 24 //Number of hours between messages (usually a multiple of 24 - 24 = daily) var active = 0 // 0 if cancelled, 1 if active init(phoneNumber: Int, message: String, frequency: Int, active: Int ){ self.phoneNumber = phoneNumber self.message = message self.frequency = frequency self.active = active } } 

NSKeyedArchiver serializa los objects aprovechando los methods que debe proporcionar al NSCoding protocolo NSCoding . No puede inferir automáticamente cómo save sus classs personalizadas; usted tiene que implementarlo usted mismo de la siguiente manera:

 class Text : NSObject, NSCoding { var phoneNumber = 0 //Text address to send to var message: String = "" //Message to be sent var frequency = 24 //Number of hours between messages (usually a multiple of 24 - 24 = daily) var active = 0 // 0 if cancelled, 1 if active init(phoneNumber: Int, message: String, frequency: Int, active: Int ){ self.phoneNumber = phoneNumber self.message = message self.frequency = frequency self.active = active } requinetworking init?(coder aDecoder: NSCoder) { phoneNumber = aDecoder.decodeInteger(forKey: "phoneNumber") message = aDecoder.decodeObject(forKey: "message") as! String frequency = aDecoder.decodeInteger(forKey: "frequency") active = aDecoder.decodeInteger(forKey: "active") } func encode(with aCoder: NSCoder) { aCoder.encode(phoneNumber, forKey: "phoneNumber") aCoder.encode(message, forKey: "message") aCoder.encode(frequency, forKey: "frequency") aCoder.encode(active, forKey: "active") } } 

Como puede ver, el inicializador lee desde el codificador y crea y instancia, mientras que el método de encode guarda información relevante para el codificador. En una class simple como esta, sus implementaciones pueden parecer obvias, pero en un tipo personalizado más complejo, hay decisiones de encoding no triviales para tomar.