问题描述
以下情况: 我使用了几个使用数据结构的设备。如果我现在为较新版本扩展结构的键,则对新结构进行编码然后进行同步。作为同步的结果,旧数据结构用于解码。当您随后与新设备同步时,新密钥已丢失。我怎样才能防止这种情况?
使用游乐场
import Foundation
struct OLD_API: Codable {
var text: String
}
struct NEW_API: Codable {
var text: String
let value: Int
}
// Init data on device with NEW data struct
var newDevice = NEW_API(text: "Dog",value: 200)
let data = try! JSONEncoder().encode(newDevice)
// .. sync to other devices (new to old)
// modified data on device with OLD data struct
var oldDevice = try! JSONDecoder().decode(OLD_API.self,from: data)
oldDevice.text = "Cat"
let newData = try! JSONEncoder().encode(oldDevice)
// .. sync to other devices (old to new)
// decode data on device with NEW data struct
newDevice = try! JSONDecoder().decode(NEW_API.self,from: newData)
print(newDevice)
解决方法
用 do catch 包裹你的最后一条 decode 语句,你会发现发生了什么
do {
newDevice = try JSONDecoder().decode(NewApi.self,from: newData)
} catch {
print(error)
}
错误将是这样的 keyNotFound(CodingKeys(stringValue: "value",intValue: nil),Swift.DecodingError.Context(codingPath: [],debugDescription: "No value associated with key CodingKeys(stringValue: "value",intValue: nil) ("value" )”,底层错误: nil))
您可以做的一件事是创建自定义解码器初始化程序
init(from decoder: Decoder) throws {
let container = try decoder.container(keyedBy: CodingKeys.self)
text = try container.decode(String.self,forKey: .text)
value = (try? container.decode(Int.self,forKey: .value) ) ?? 0
}
并为“value”属性提供默认值(如果未找到)
我建议您将此说服 init 移至“NewApi”结构的扩展,以免丢失默认初始化程序。