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



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

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

有什么想法吗?感谢

此处保存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)
}

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

如果你想要一个外部依赖,可以节省大量的挫折感,请签出SwifterSwift

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

用于设置:

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

用于检索对象:

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

就这样。。!!

基本上,您的UserDefault存储属性将看起来像这样,

private let userDefaults = UserDefaults.standard
var configuration: Configuration? {
get {
do {
let data = userDefaults.data(forKey: "configuration_key")
if let data {
let config = try JSONDecoder().decode(User.self, from: data)
return config
}
} catch let error {
print("Preference (#function) json decode error: (error.localizedDescription)")
}
return nil
} set {
do {
let data = try JSONEncoder().encode(newValue)
userDefaults.set(data, forKey: "configuration_key")
} catch let error {
print("Preference (#function) json encode error: (error.localizedDescription)")
}
}
}

最新更新