Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/swift/20.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Swift 如何防止api更改时解码/编码时丢失密钥?_Swift_Encoding_Decode_Encode_Decoding - Fatal编程技术网

Swift 如何防止api更改时解码/编码时丢失密钥?

Swift 如何防止api更改时解码/编码时丢失密钥?,swift,encoding,decode,encode,decoding,Swift,Encoding,Decode,Encode,Decoding,以下情况: 我使用了几个使用数据结构的设备。如果我现在展开新版本结构的键,新结构将被编码,然后同步。作为同步的结果,旧数据结构用于解码。然后与新设备同步时,新密钥已丢失。我怎样才能防止这种情况 使用操场 import Foundation struct OLD_API: Codable { var text: String } struct NEW_API: Codable { var text: String let value: Int } // Init data on

以下情况: 我使用了几个使用数据结构的设备。如果我现在展开新版本结构的键,新结构将被编码,然后同步。作为同步的结果,旧数据结构用于解码。然后与新设备同步时,新密钥已丢失。我怎样才能防止这种情况

使用操场

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包装您的最后一条解码语句,您将发现发生了什么

  do {
   newDevice = try JSONDecoder().decode(NewApi.self, from: newData)
} catch {
   print(error)
}
错误是这样的 keyNotFound(编码键(stringValue:“值”,intValue:nil),Swift.DecodingError.Context(编码路径:[],调试说明:“没有与键编码键关联的值(stringValue:“值”,intValue:nil)(“值”),UnderlineingError: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”属性,则为其提供默认值


我建议您将此Converse init移到“NewApi”结构的扩展中,以避免丢失默认初始值设定项。

这是一个好问题--但是,请发布代码,而不是代码图片,因为它们不可搜索,不可复制/复制,在移动设备或屏幕阅读器上也不能很好地工作。当然,它们会丢失,因为旧的API不知道新的密钥。您可以将新密钥声明为可选的。我完全同意jnpdx。@添加了jnpdx代码。不幸的是,可选密钥不是解决方案。我想避免丢失信息@Vadian如果使用旧API对数据进行编码,而旧API只是删除了新的密钥,这是不可能的。问题不是上面的代码崩溃了,而是数据丢失了。如果我在我的应用程序中创建了一个新值(用户输入),则在与旧设备同步时,该值将被删除。所以问题是,我怎样才能与旧设备同步,而不丢失带值的新密钥。