Неопознанный селектор Swift 3 NSCoder отправлен в экземпляр

Я пытаюсь сохранить список пользовательского класса по умолчанию для пользователя, и при сохранении я продолжаю получать сообщение об ошибке «неопознанный селектор, отправленный в экземпляр». У меня нет проблем с получением массива из пользовательских значений по умолчанию.

Это код, который я использую для сохранения пользовательских настроек по умолчанию.

let userDefaults = UserDefaults.standard
        userDefaults.set(NSKeyedArchiver.archivedData(withRootObject: visitors), forKey: "signedInUsers")
        userDefaults.synchronize()

Посетители — это массив объектов Visitor.

Вот мой класс посетителей.

class Visitor: NSObject {
    var name: String = ""
    var contactEmail: String = ""
    var company: String = ""
    var picture: UIImage = UIImage()
    var signature: UIImage = UIImage()
    var timeIn: String = ""
    var timeOut: String = ""
    var signedOut: Bool = false
    var otherQuestionsWithAnswers: [String] = []

    // MARK: NSCoding

    override init() {
        super.init()
    }

    init(name: String, contactEmail: String, company: String, picture: UIImage, signature: UIImage,timeIn: String,timeOut: String,signedOut: Bool,otherQuestionsWithAnswers: [String]) {
        self.name = name
        self.contactEmail = contactEmail
        self.company = company
        self.picture = picture
        self.signature = signature
        self.timeIn = timeIn
        self.timeOut = timeOut
        self.signedOut = signedOut
        self.otherQuestionsWithAnswers = otherQuestionsWithAnswers
    }

    required convenience init?(coder decoder: NSCoder) {
        guard let name = decoder.decodeObject(forKey: "name") as? String,
            let contactEmail = decoder.decodeObject(forKey: "contactEmail") as? String,
            let company = decoder.decodeObject(forKey: "company") as? String,
            let timeOut = decoder.decodeObject(forKey: "timeOut") as? String,
            let timeIn = decoder.decodeObject(forKey: "timeIn") as? String,
            let picture = decoder.decodeObject(forKey: "picture") as? UIImage,
            let signature = decoder.decodeObject(forKey: "signature") as? UIImage,
            let otherQuestionsWithAnswers = decoder.decodeObject(forKey: "otherQuestionsWithAnswers") as? [String],
            let signedOut = decoder.decodeObject(forKey: "signedOut") as? Bool
            else { return nil }

        self.init(
            name: name,
            contactEmail: contactEmail,
            company: company,
            picture: picture,
            signature: signature,
            timeIn: timeIn,
            timeOut: timeOut,
            signedOut: signedOut,
            otherQuestionsWithAnswers: otherQuestionsWithAnswers
        )
    }

    func encodeWithCoder(coder: NSCoder) {
        coder.encode(name, forKey: "name")
        coder.encode(contactEmail, forKey: "contactEmail")
        coder.encode(company, forKey: "company")
        coder.encode(picture, forKey: "picture")
        coder.encode(signature, forKey: "signature")
        coder.encode(timeIn, forKey: "timeIn")
        coder.encode(timeOut, forKey: "timeOut")
        coder.encode(signedOut, forKey: "signedOut")
        coder.encode(otherQuestionsWithAnswers, forKey: "otherQuestionsWithAnswers")
    }
}

Спасибо помощь приветствуется.

РЕДАКТИРОВАТЬ:

Изменение класса на это исправило это.

import Foundation
import UIKit

// a question that the user has to answer
class Visitor: NSObject, NSCoding {
    var name: String = ""
    var contactEmail: String = ""
    var company: String = ""
    var picture: UIImage = UIImage()
    var signature: UIImage = UIImage()
    var timeIn: String = ""
    var timeOut: String = ""
    var signedOut: Bool = false
    var otherQuestionsWithAnswers: [String] = []

    // MARK: NSCoding

    override init() {
        super.init()
    }

    init(name: String, contactEmail: String, company: String, picture: UIImage, signature: UIImage,timeIn: String,timeOut: String,signedOut: Bool,otherQuestionsWithAnswers: [String]) {
        self.name = name
        self.contactEmail = contactEmail
        self.company = company
        self.picture = picture
        self.signature = signature
        self.timeIn = timeIn
        self.timeOut = timeOut
        self.signedOut = signedOut
        self.otherQuestionsWithAnswers = otherQuestionsWithAnswers
    }

    required init(coder decoder: NSCoder) {
        name = decoder.decodeObject(forKey: "name") as! String
        contactEmail = decoder.decodeObject(forKey: "contactEmail") as! String
        company = decoder.decodeObject(forKey: "company") as! String
        timeOut = decoder.decodeObject(forKey: "timeOut") as! String
        timeIn = decoder.decodeObject(forKey: "timeIn") as! String
        if let pictureTest = decoder.decodeObject(forKey: "picture") as? UIImage {
            picture = pictureTest
        } else {
            picture = UIImage()
        }
        if let sigTest = decoder.decodeObject(forKey: "picture") as? UIImage {
            signature = sigTest
        } else {
            signature = UIImage()
        }
        otherQuestionsWithAnswers = decoder.decodeObject(forKey: "otherQuestionsWithAnswers") as! [String]
        signedOut = decoder.decodeBool(forKey: "signedOut")
    }

    public func encode(with aCoder: NSCoder) {
        aCoder.encode(name, forKey: "name")
        aCoder.encode(contactEmail, forKey: "contactEmail")
        aCoder.encode(company, forKey: "company")
        aCoder.encode(picture, forKey: "picture")
        aCoder.encode(signature, forKey: "signature")
        aCoder.encode(timeIn, forKey: "timeIn")
        aCoder.encode(timeOut, forKey: "timeOut")
        aCoder.encode(signedOut, forKey: "signedOut")
        aCoder.encode(otherQuestionsWithAnswers, forKey: "otherQuestionsWithAnswers")
    }
}

person Vlad Lund    schedule 30.06.2017    source источник
comment
Какой конкретный селектор не распознается? Включите полное сообщение об ошибке, которое вы видите.   -  person Itai Ferber    schedule 01.07.2017
comment
хороший вопрос. такая же проблема здесь. хороший код. с нетерпением жду ответа на этот великий вопрос.   -  person Adrian Borcea    schedule 01.07.2017
comment
как говорит @ItaiFerber, какой селектор не распознан?   -  person Reinier Melian    schedule 01.07.2017
comment
какую быструю версию вы используете?   -  person Reinier Melian    schedule 01.07.2017
comment
«NSInvalidArgumentException», причина: «-[Visitor_Manager.Visitor encodeWithCoder:]: нераспознанный селектор отправлен экземпляру 0x14e33400» swift 3. Все еще говорит кодировать с помощью кодера после того, как я удалил эту функцию   -  person Vlad Lund    schedule 01.07.2017


Ответы (2)


Функция, которую вы используете для кодирования, неверна, должна быть func encode(with aCoder: NSCoder){} вместо func encodeWithCoder(coder: NSCoder) {}, поэтому измените ее и она будет работать как задумано.

public func encode(with aCoder: NSCoder) {
    aCoder.encode(name, forKey: "name")
    aCoder.encode(contactEmail, forKey: "contactEmail")
    aCoder.encode(company, forKey: "company")
    aCoder.encode(picture, forKey: "picture")
    aCoder.encode(signature, forKey: "signature")
    aCoder.encode(timeIn, forKey: "timeIn")
    aCoder.encode(timeOut, forKey: "timeOut")
    aCoder.encode(signedOut, forKey: "signedOut")
    aCoder.encode(otherQuestionsWithAnswers, forKey: "otherQuestionsWithAnswers")
}

Надеюсь это поможет

person Reinier Melian    schedule 01.07.2017
comment
Хм... Кажется, все еще не работает. Спасибо за ответ - person Vlad Lund; 01.07.2017
comment
@VincentLandolfi вы очистили свой проект и повторили попытку? - person Reinier Melian; 01.07.2017

Ваш класс Visitor должен сначала наследоваться от NSObject, а затем от NSCoding. Без NSCoding вы не сможете кодировать и декодировать пользовательские классы. Это недавняя ошибка, которую я сделал в своем проекте, и ваша подпись функции кодирования неверна. Я уверен, что это решит эту проблему. Вот исправленный код:

Версия Swift 3: -

class Visitor: NSObject, NSCoding {
    var name: String = ""
    var contactEmail: String = ""
    var company: String = ""
    var picture: UIImage = UIImage()
    var signature: UIImage = UIImage()
    var timeIn: String = ""
    var timeOut: String = ""
    var signedOut: Bool = false
    var otherQuestionsWithAnswers: [String] = []

func encode(with aCoder: NSCoder) {
//... encode here
}
person Dark Innocence    schedule 01.07.2017
comment
Все еще не работает. Спасибо за ответ. - person Vlad Lund; 01.07.2017
comment
можете ли вы поставить точку останова в этом операторе защиты и посмотреть, возвращает ли он nil ? - person Dark Innocence; 01.07.2017
comment
Пробовал, не похоже, что ничего нулевое - person Vlad Lund; 04.07.2017