我正在尝试对结构进行编码
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)
}
JSONEncoder
的encode(_:)
函数返回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
中的所有案例赋值,这些值会自动成为案例的名称 - 如果同时符合
Encodable
和Decodable
,则可以简单地使用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)")
}
}
}