I have downloaded a swift file that should help me with saving and loading custom variables:
import Foundation
protocol ObjectSavable {
func setToObject<Object>(_ object: Object, forKey: String) throws where Object: Encodable
func getToObject<Object>(forKey: String, castTo type: Object.Type) throws -> Object where Object: Decodable
}
extension UserDefaults: ObjectSavable {
func setToObject<Object>(_ object: Object, forKey: String) throws where Object: Encodable {
let encoder = JSONEncoder()
do {
let data = try encoder.encode(object)
set(data, forKey: forKey)
} catch {
throw ObjectSavableError.unableToEncode
}
}
func getToObject<Object>(forKey: String, castTo type: Object.Type) throws -> Object where Object: Decodable {
guard let data = data(forKey: forKey) else { throw ObjectSavableError.noValue }
let decoder = JSONDecoder()
do {
let object = try decoder.decode(type, from: data)
return object
} catch {
throw ObjectSavableError.unableToDecode
}
}
}
enum ObjectSavableError: String, LocalizedError {
case unableToEncode = "Unable to encode object into data"
case noValue = "No data object found for the given key"
case unableToDecode = "Unable to decode object into given type"
}
And I have this Person
struct:
struct Person: Encodable, Decodable {
var firstName: String
var lastName: String
var birthday: Date
init() {
self.firstName = "Tim"
self.lastName = "Cook"
self.birthday = Date()
}
}
And I also have this code for saving/loading a Person
struct (that is using the code from above)
Saving:
print("Saving object...")
let person: Person = Person()
do {
try UserDefaults.standard.setToObject(person, forKey: "person")
print("Object saved successfully")
} catch let err {
print("Error while saving object:\n\(err.localizedDescription)")
}
Loading:
print("Loading object...")
do {
self.person = try UserDefaults.standard.getToObject(forKey: "person", castTo: Person.self)
print("Successfully load object:\n\(self.person!)")
} catch let err {
print("Error while loading object:\n\(err.localizedDescription)")
}
Now, all of this does work.
But, let's say that I release my app that way, and then I want to add a new variable to Person
, for example, I'll add a favorite
:
struct Person: Encodable, Decodable {
var firstName: String
var lastName: String
var birthday: Date
var favorite: Bool = false
init() {
self.firstName = "Tim"
self.lastName = "Cook"
self.birthday = Date()
}
}
Before the update, the app (without the favorite
variable in Person
) would save without the favorite
variable. And after the update, the app will try to load the previous saved Person
with the favorite
variable. And that is where it failes, because the older-version data doesn't have a favorite
variable in it. So it throws an error.
And my question is, is there a way that when it decoding a Person
from User Defaults, if it doesn't find any matching variable (for example: favorite
), instead of throwing an error, it will try to auto-create it? (from var favorite
= false
)?
My project: https://github.com/orihpt/Encodable
Thanks in advance.