Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How to save custom objects that implements Codable

Tags:

ios

swift

swift4

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.

like image 603
Damien Avatar asked Jun 12 '17 09:06

Damien


2 Answers

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)
}
like image 53
Anish Parajuli 웃 Avatar answered Oct 31 '22 18:10

Anish Parajuli 웃


Swift 5: a great simple extension for 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
    }
}

Usage

save

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

get

let user: User? = UserDefaults.standard.getObject(forKey: "currentUser")
like image 21
Musa almatri Avatar answered Oct 31 '22 19:10

Musa almatri