NSKeyedArchiver не может заархивировать объект - PullRequest
0 голосов
/ 21 марта 2020

У меня есть JSON файл, который я читаю с диска

Это структура файла:

[
{
    "name": "3X",
    "priority": 33
},
{
    "name": "4X",
    "priority": 32
}
]

Я декодирую его в класс с именем Test

class TestClass: NSObject, Codable {

    enum CodingKeys: String, CodingKey {
        case name, priority
    }

    let name:String
    let priority:Int

    var optional:String? = nil
    var problem:String = "eli"

    init(name:String, priority:Int, optional:String? = nil, problem:String) {
        self.name = name
        self.priority = priority
        self.optional = optional
        self.problem = problem
        super.init()
    }

}

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

    if let path = Bundle.main.path(forResource: "test", ofType: "json") {
        do {
            let jsonData = try Data(contentsOf: URL(fileURLWithPath: path), options: .mappedIfSafe)
            let testObjects = try JSONDecoder().decode([TestClass].self, from: jsonData)
            let data = try! NSKeyedArchiver.archivedData(withRootObject: testObjects, requiringSecureCoding: false)
            UserDefaults.standard.set(data, forKey: "test_objects")
        } catch {
            // error in parsing json
        }
    }

После декодирования я пытаюсь сохранить массив на диск, однако я преобразовываю его в NSData для сохранения, однако NSKeyedArchiver.archivedData терпит неудачу со следующей ошибкой:

{NSDebugDescription=Caught exception during archival: -[BugTesting.TestClass encodeWithCoder:]: unrecognized selector sent to instance 0x600002119ac0

Для меня это выглядит очень странно, поскольку я согласен с Codable.

Любая помощь будет оценена.

1 Ответ

1 голос
/ 21 марта 2020

Если вы хотите закодировать это, я могу предложить PropertyListEncoder. Тогда вам не нужно вводить NSObject (или NSCoding / NSSecureCoding cruft), связанное с NSKeyedArchiver:

class TestClass: Codable {
    enum CodingKeys: String, CodingKey {
        case name, priority
    }

    let name: String
    let priority: Int

    var optional: String?
    var problem: String?

    init(name: String, priority: Int, optional: String? = nil, problem: String? = nil) {
        self.name = name
        self.priority = priority
        self.optional = optional
        self.problem = problem
    }
}

Затем для кодирования:

let data = try PropertyListEncoder().encode(test)

И для декодирования:

let test2 = try PropertyListDecoder().decode(TestClass.self, from: data)

Я не уверен, почему вы не закодировали бы optional или problem. Я бы, вероятно, тоже был склонен их кодировать, если только не было какой-либо причины, по которой вы хотели потерять эти данные в процессе кодирования / декодирования. Если вы хотите, чтобы все свойства были закодированы, вы можете просто исключить CodingKeys:

class TestClass: Codable {
    let name: String
    let priority: Int

    var optional: String?
    var problem: String?

    init(name: String, priority: Int, optional: String? = nil, problem: String? = nil) {
        self.name = name
        self.priority = priority
        self.optional = optional
        self.problem = problem
    }
}
...