使用Swift将可编码结构保存为UserDefaults

使用Swift将可编码结构保存为UserDefaults,swift,codable,userdefaults,Swift,Codable,Userdefaults,我正在尝试对结构进行编码 struct Configuration : Encodable, Decodable { private enum CodingKeys : String, CodingKey { case title = "title" case contents = "contents" } var title : String? var contents: [[Int]]? } 转换为JSON以存储在UserDe

我正在尝试对结构进行编码

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中,它始终不返回任何配置

let defaults = UserDefaults.standard
        let config = defaults.string(forKey: "simulationConfiguration") ?? "No Config"
        print("from app delegate = \(config.description)")
有什么想法吗?谢谢
encode(:)
函数的
jsonecoder
返回
数据
,而不是
字符串
。这意味着当您需要从
UserDefaults
获取
配置时,您需要获取数据并对其进行解码。
下面是一个例子:

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
    中的所有案例赋值,这些值将自动成为案例的名称
  • 如果您同时符合这两种标准,
    Encodable
    Decodable
    ,您可以简单地使用
    Codable
    ,因为它是这两种标准的组合,定义为
    typealias Codable=Encodable&Decodable

这里保存的是一个
数据
值(正确)

但这里您正在阅读一个
字符串

defaults.string(forKey: "simulationConfiguration")
您不能保存
数据
,读取
字符串
,并期望它正常工作

让我们修复您的代码 首先,您不需要手动指定编码键。所以你的结构变得简单了

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)
}

如果您想要一个外部依赖项来避免一船的挫折感,请签出

下面是我如何使用UserDefaults扩展在两行中完成的

设置:

UserDefaults.standard.set(object: configuration, forKey: "configuration")
要检索对象,请执行以下操作:

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

就这样

成功了!谢谢你的解释。你应该只需要在你的类上实现配置:Codable。
guard let configuration = UserDefaults.standard.object(Configuration.self, with: "configuration") else { return }
print(configuration)