首页 > 解决方案 > 在 NSUserDefaults 中存储嵌套对象

问题描述

我正在尝试使用 mutated 属性存储自定义可编码结构,但我总是获得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

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

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

标签: iosswiftnsuserdefaults

解决方案


由于您CodingKeys在 Test1 中,您需要添加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
    }
}

检查编码和解码自定义类型

...可编码类型可以声明一个名为 CodingKeys 的特殊嵌套枚举,该枚举符合 CodingKey 协议。当此枚举存在时,它的案例充当权威的属性列表,在编码或解码可编码类型的实例时必须包含这些属性。枚举用例的名称应与您为类型中的相应属性指定的名称相匹配。


推荐阅读