在 NSUserDefaults 中存储嵌套对象

Storing nested objects in NSUserDefaults

我正在尝试存储具有变异 属性 的自定义可编码结构,但我总是得到 nil 属性。

例如,具有可编码结构:

struct Test1: Codable {
    var testDate: Date? = nil
    let name: String
    let age: Int

    enum CodingKeys: String, CodingKey {
        case name
        case age
    }
}

使用以下示例 JSON 我们将解码提供的结构,并分配自定义 属性 testDate:

let json = """
{
"name": "test",
"age": 30,
}
"""


let jsonData = Data(json.utf8)
var test1 = try? JSONDecoder().decode(Test1.self, from: jsonData)
test1?.testDate = Date()

然后我们将尝试将此结构存储在 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")
    }
}

虽然这适用于所有可编码属性,但当我尝试访问自定义 属性 时,例如 testDate 我得到的是 nil:

currentTest?.testDate = nil

有没有办法存储 "nested" 属性而不将它们作为单独的实例存储在 UserDefautls 中?

要点示例 - https://gist.github.com/ignotusverum/0cb9b57eef021eed3680530df519cedf

因为你在Test1中有CodingKeys,你需要添加case testDate 否则属性 testDate在解码实例时会被省略。

struct Test1: Codable {
    var testDate: Date? = nil
    let name: String
    let age: Int

    enum CodingKeys: String, CodingKey {
        case name
        case age
        case testDate
    }
}

勾选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.