How to save custom objects that implements Codable

2019-03-26 20:22发布

It's now easier with Swift 4 to encode / decode to and from JSON or Properties list.

But I can't find how to encode to Data using Codable, without using Objective-C methods initWithCoder and encodeWithCoder.

Considering this simple class:

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

How can I encode it to Data using CodingKeys and not initWithCoder and encodeWithCoder?

EDIT: I also need to be able to deserialize objects previously saved in userdefaults using NSKeyedArchiver.

标签: ios swift swift4
3条回答
在下西门庆
2楼-- · 2019-03-26 20:57

Well, you no longer need NSKeyedArchiver.

Try this:

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)
}
查看更多
欢心
3楼-- · 2019-03-26 21:01
struct Question: Codable {
    var title: String
    var answer: Int
    var question: Int
}

class UserDefaults_Question {
    static let key = "myapp.trick.question"

    static var value: UserDefaults_Question? {
        get {
            guard let data = UserDefaults.standard.data(forKey: key) else {
                print("no model for key: \(key)")
                return nil
            }
            guard let model = try? JSONDecoder().decode(UserDefaults_Question.self, from: data) else {
                print("failed to decode model for key: \(key)")
                return nil
            }
            print("did load model for key: \(key)")
            return model
        }
        set {
            guard let value = newValue, let data: Data = try? JSONEncoder().encode(value) else {
                print("removing model for key: \(key)")
                UserDefaults.standard.removeObject(forKey: key)
                return
            }
            print("inserting model for key: \(key)")
            UserDefaults.standard.set(data, forKey: key)
        }
    }
}

UserDefaults_Question.value = Question(title: "Next President", answer: 666, question: -1)
查看更多
Bombasti
4楼-- · 2019-03-26 21:19

Well it can be achieved via JSONEncoder and 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)
    }
}
查看更多
登录 后发表回答