How to save custom objects that implements Codable

2019-03-26 20:17发布

问题:

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.

回答1:

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


回答2:

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


回答3:

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)


标签: ios swift swift4