【问题标题】:Saving a Codable Struct to UserDefaults with Swift使用 Swift 将可编码结构保存到 UserDefaults
【发布时间】:2019-01-12 18:51:53
【问题描述】:

我正在尝试编码一个结构

struct Configuration : Encodable, Decodable {
    private enum CodingKeys : String, CodingKey {
        case title = "title"
        case contents = "contents"
    }
    var title : String?
    var contents: [[Int]]?
}

转换成 JSON 以存储在 UserDefaults.standard 的本地键中。我有以下代码:

let jsonString = Configuration(title: nameField.text, contents: newContents)
let info = ["row" as String: jsonString as Configuration]
print("jsonString = \(jsonString)")
//trying to save object
let defaults = UserDefaults.standard
let recode = try! JSONEncoder().encode(jsonString)
defaults.set(recode, forKey: "simulationConfiguration")
//end of saving local

打印返回:

jsonString = Configuration(title: Optional("config"), contents: Optional([[4, 5], [5, 5], [6, 5]]))

所以我相信我正在正确地创建对象。但是,当我下次运行模拟器时尝试检索密钥时,我什么也得不到。 我将以下内容放在 AppDelegate 中,它总是返回 No Config。

let defaults = UserDefaults.standard
        let config = defaults.string(forKey: "simulationConfiguration") ?? "No Config"
        print("from app delegate = \(config.description)")

有什么想法吗?谢谢

【问题讨论】:

    标签: swift codable userdefaults


    【解决方案1】:

    在这里你保存了一个Data 值(这是正确的)

    defaults.set(recode, forKey: "simulationConfiguration")
    

    但是在这里你正在阅读String

    defaults.string(forKey: "simulationConfiguration")
    

    您无法保存 Data,阅读 String 并期望它能够正常工作。

    让我们修复您的代码

    首先,您不需要手动指定编码键。所以你的结构就变成了这个

    struct Configuration : Codable {
        var title : String?
        var contents: [[Int]]?
    }
    

    保存

    现在是保存它的代码

    let configuration = Configuration(title: "test title", contents: [[1, 2, 3]])
    if let data = try? JSONEncoder().encode(configuration) {
        UserDefaults.standard.set(data, forKey: "simulationConfiguration")
    }
    

    加载中

    这是阅读它的代码

    if
        let data = UserDefaults.standard.value(forKey: "simulationConfiguration") as? Data,
        let configuration = try? JSONDecoder().decode(Configuration.self, from: data) {
        print(configuration)
    }
    

    【讨论】:

    • 做到了!谢谢你的解释。
    【解决方案2】:

    JSONEncoderencode(_:) 函数返回Data,而不是String。这意味着当您需要从UserDefaults 取回Configuration 时,您需要获取数据并对其进行解码。 这是一个例子:

    let defaults = UserDefaults.standard
    guard let configData = defaults.data(forKey: "simulationConfiguration") else {
      return nil // here put something or change the control flow to if statement
    }
    return try? JSONDecoder().decode(Configuration.self, from: configData)
    

    • 您也不需要为CodingKeys 中的所有案例赋值,这些值自动为案例的名称
    • 如果您同时符合EncodableDecodable,您可以简单地使用Codable,因为它是两者的组合并定义为typealias Codable = Encodable & Decodable

    【讨论】:

      【解决方案3】:

      如果您想要一个外部依赖项来节省大量的挫败感,请查看SwifterSwift

      这是我如何使用他们的 UserDefaults 扩展在两行中完成的。

      设置:

      UserDefaults.standard.set(object: configuration, forKey: "configuration")
      

      用于检索对象:

      guard let configuration = UserDefaults.standard.object(Configuration.self, with: "configuration") else { return }
      print(configuration)
      

      就是这样..!!

      【讨论】:

      • 你应该只需要在你的类上实现 Configuration : Codable 。
      猜你喜欢
      • 2017-12-06
      • 1970-01-01
      • 2021-02-07
      • 1970-01-01
      • 2017-05-09
      • 1970-01-01
      • 2014-12-15
      • 1970-01-01
      相关资源
      最近更新 更多