I'm trying to store custom codable struct with mutated property, but I'm always getting nil
for that property.
For example, having codable struct:
struct Test1: Codable {
var testDate: Date? = nil
let name: String
let age: Int
enum CodingKeys: String, CodingKey {
case name
case age
}
}
with the following example JSON we will decode provided struct, and assign custom property testDate
:
let json = """
{
"name": "test",
"age": 30,
}
"""
let jsonData = Data(json.utf8)
var test1 = try? JSONDecoder().decode(Test1.self, from: jsonData)
test1?.testDate = Date()
Then we will try to store this struct in userDefaults:
var currentTest: Test1? {
get {
let defaults = UserDefaults.standard
guard let testData = defaults.object(forKey: "test1") as? Data,
let test = try? PropertyListDecoder().decode(Test1.self,
from: testData) else {
return nil
}
return test
}
set {
let defaults = UserDefaults.standard
defaults.set(try? PropertyListEncoder().encode(newValue), forKey: "test1")
}
}
While this works for all of the codable properties, when I try to access a custom property, such as testDate
I'm getting nil:
currentTest?.testDate = nil
Is there a way to store "nested" properties without storing them as a separate instance in UserDefautls?
gist example - https://gist.github.com/ignotusverum/0cb9b57eef021eed3680530df519cedf
Since you have CodingKeys
in Test1, you need to add case testDate
or property testDate will be omitted when decoding instances.
struct Test1: Codable {
var testDate: Date? = nil
let name: String
let age: Int
enum CodingKeys: String, CodingKey {
case name
case age
case testDate
}
}
Check Encoding and Decoding Custom Types,
...Codable types can declare a special nested enumeration named CodingKeys that conforms to the CodingKey protocol. When this enumeration is present, its cases serve as the authoritative list of properties that MUST be included when instances of a codable type are encoded or decoded. The names of the enumeration cases should match the names you've given to the corresponding properties in your type.