Как сохранить пользовательские объекты, реализующие Codable

С Swift 4 теперь стало проще кодировать / декодировать в JSON или список свойств и обратно. .

Но я не могу найти, как кодировать данные с помощью Codable без использования методов Objective-C initWithCoder и encodeWithCoder.

Учитывая этот простой класс:

struct Question: Codable {
    var title: String
    var answer: Int
    var question: Int
}

Как я могу закодировать его в данные, используя CodingKeys, а не initWithCoder и encodeWithCoder?

EDIT: мне также нужно иметь возможность десериализовать объекты, ранее сохраненные в userdefaults, с помощью NSKeyedArchiver.


person Damien    schedule 12.06.2017    source источник
comment
Он подробно описан (и на Swift) в документации.   -  person vadian    schedule 12.06.2017
comment
Извините, если мой вопрос был неполным, но мне нужно десериализовать объекты, которые были сохранены с помощью NSKeyedArchiver. Поэтому я думаю, что JSONEncoder или PropertyListEncoder там не будут работать, не так ли?   -  person Damien    schedule 12.06.2017
comment
@Damien, вы имеете в виду сохранение в пользовательских настройках и извлечение из них, как вы делаете с NSKeyedArchiver?   -  person Anish Parajuli 웃    schedule 12.06.2017
comment
@ThatlazyiOSGuy 웃 да, именно так, извините, если было непонятно   -  person Damien    schedule 12.06.2017


Ответы (3)


Что ж, тебе больше не нужен NSKeyedArchiver.

Попробуй это:

let questionObj = Question(title: "WWDC, 2017", answer: 1,question:1)
let encoder = JSONEncoder()
if let encoded = try? encoder.encode(questionObj) {
    UserDefaults.standard.set(encoded, forKey: "K_Question")
}
let decoder = JSONDecoder()
if let questionData = UserDefaults.standard.data(forKey: "K_Question"),
    let question = try? decoder.decode(Question.self, from: questionData) {
    print(question.title)
    print(question.answer)
    print(question.question)
}
person Anish Parajuli 웃    schedule 12.06.2017
comment
Спасибо! Значит, мы можем использовать JSONEncoder, а также PropertyListEncoder? Есть идеи, что быстрее? - person Damien; 12.06.2017
comment
Я не пробовал PropertyListEncoder .. Задайте ему отдельный вопрос. - person Anish Parajuli 웃; 12.06.2017
comment
Как декодировать объект массива вопросов из JSONDecoder? - person ArgaPK; 07.07.2021

Swift 5: отличное простое расширение для UserDefaults:

extension UserDefaults {

    func save<T: Codable>(_ object: T, forKey key: String) {
        let encoder = JSONEncoder()
        if let encodedObject = try? encoder.encode(object) {
            UserDefaults.standard.set(encodedObject, forKey: key)
            UserDefaults.standard.synchronize()
        }
    }

    func getObject<T: Codable>(forKey key: String) -> T? {
        if let object = UserDefaults.standard.object(forKey: key) as? Data {
            let decoder = JSONDecoder()
            if let decodedObject = try? decoder.decode(T.self, from: object) {
                return decodedObject
            }
        }
        return nil
    }
}

Использование

сохранить

UserDefaults.standard.save(currentUser, forKey: "currentUser")

получить

let user: User? = UserDefaults.standard.getObject(forKey: "currentUser")
person Musa almatri    schedule 11.09.2019
comment
Общий параметр "T" не может быть выведен - person Utku Dalmaz; 09.05.2020

Ну, это можно сделать с помощью JSONEncoder и JSONDecoder.

struct Question: Codable {
    var title: String
    var answer: Int
    var question: Int
}

let questionObj = Question(title: "Swift", answer: "Open Source",question:1)


let encoder = JSONEncoder()
if let encoded = try? encoder.encode(questionObj) {
    if let json = String(data: encoded, encoding: .utf8) {
        print(json)
    }

    let decoder = JSONDecoder()
    if let decoded = try? decoder.decode(Question.self, from: encoded) {
        print(decoded)
    }
}
person ankit    schedule 12.06.2017
comment
Этот код не работает - значение вопроса не соответствует кодируемым / декодируемым - person UKDataGeek; 29.07.2018