Swift - сохранение пользовательских данных с использованием NSKeyedArchiver, получение ошибки при преобразовании в NSArray

Итак, у меня есть массив пользовательских объектов. Когда я пытаюсь сохранить массив в NSUserDefaults, я должен заархивировать их. Вот что я делаю, чтобы заархивировать массив моих пользовательских объектов:

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
}

Поток это:

  1. При вызове saveMessage передайте пользовательский массив для архивации. Вот как выглядит массив для GDB. Вы можете видеть, что это массив, и в нем содержится 1 объект класса.

    ([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. Массив передается в archiveMessage. Код немедленно завершается ошибкой в ​​методе NSKeyedArchiver. Сообщение об ошибке выглядит следующим образом:

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

    2016-07-15 16: 31: 26.019 Harass Your Kate [5858: 7847495] * - [NSKeyedArchiver dealloc]: предупреждение: NSKeyedArchiver освобожден без вызова -finishEncoding. 2016-07-15 16: 31: 26.023 беспокоить вашу Кейт [5858:7847495] * Завершение работы приложения из-за необработанного исключения "NSInvalidArgumentException", причина: '-[_TtCC16Harass_Your_Kate24AddMessageViewController10harassText encodeWithExogn0000 отправлено: 0505: 0

Я ценю всю помощь, спасибо заранее!

РЕДАКТИРОВАТЬ: Вот определение моего объекта:

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
    }
}

1 ответ

Решение

NSKeyedArchiver сериализует объекты, используя методы, которые вы должны предоставить, в соответствии с NSCoding протокол. Он не может автоматически определить, как сохранить ваши пользовательские классы; Вы должны реализовать это самостоятельно следующим образом:

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
    }

    required 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")
    }
}

Как вы можете видеть, инициализатор читает кодер и создает и экземпляр, тогда как encode Метод сохраняет соответствующую информацию для кодера. В таком простом классе их реализации могут показаться очевидными, но в более сложном настраиваемом типе существуют нетривиальные решения по кодированию.

Другие вопросы по тегам