ios - 如何快速传递关联类型中的 Codable 对象

标签 ios swift

我有来自服务器的以下数据

{ 
  "success": true,
  "terms": "https://currencylayer.com/terms",
  "privacy": "https://currencylayer.com/privacy",
  "timestamp": 1572365346,
  "source": "USD",
  "quotes": {
             "USDBAM": 1.76456,
             "USDTJS": 9.694558,
             "USDYER": 250.349994,
             "USDZAR": 14.592897,
             .......
            }
}

现在我创建了以下内容以使用 Codable

处理上述响应
struct Resource<T: Decodable>: ItemList {

    var quotes: Dictionary<String, Double>
    var success: Bool
    var terms: String
    var privacy: String
    var timestamp: Int
    var source: String
}

protocol ItemList: Decodable {

    associatedtype T: 
    var success: Bool {get}
    var terms: String {get}
    var privacy: String {get}
    var timestamp: Int {get}
    var source: String {get}
    var quotes: T {get}
}

一切正常,但我想将“引号”作为单独的模型,所以我创建了另一个结构,如下所示

struct CurrencyModel: Decodable {
  var quotes: Dictionary<String, Double>
}

修改后的'Resource'如下

struct Resource<T: Decodable>: ItemList {
    var quotes: T
    var success: Bool
    var terms: String
    var privacy: String
    var timestamp: Int
    var source: String
}

然后打电话

CurrencyLayerCommunicator().get(Resource<CurrencyModel>.self) { [weak self] item in
  self?.handleResult(item)
}

但是这次我无法得到结果&得到解码错误

Failed to convert into JSON with error: The data couldn’t be read because it is missing.

请建议或指导如何解决此问题。

最佳答案

最大的错误是只打印error.localizedDescription而不是 error .

有了这个:

do {
    let decoded = try JSONDecoder().decode(Resource<CurrencyModel>.self, from: jsonData)
    print(decoded)
} catch {
    print("Localized Description Error: \(error.localizedDescription)")
    print("Full Error: \(error)")
}

你将拥有:

Localized Description Error: The data couldn’t be read because it is missing.
Full Error: keyNotFound(CodingKeys(stringValue: "quotes", intValue: nil), Swift.DecodingError.Context(codingPath: [CodingKeys(stringValue: "quotes", intValue: nil)], debugDescription: "No value associated with key CodingKeys(stringValue: \"quotes\", intValue: nil) (\"quotes\").", underlyingError: nil))

更有用。

那么问题是你有两次 "quotes" .

一个作为 ItemList 中的键, 另一个在 CurrencyModel .

替换Resource<CurrencyModel>.selfResource<[String: Double]>.self它正在运行。

在 JSON 解码的情况下,我还建议当它不工作时为了调试打印反向版本(我在你的结构中用 Decodable 替换了 Codable):

let currencyModel = CurrencyModel(quotes: ["Currency1": 0.1,
                                           "Currency2": 0.2,
                                           "Currency3": 0.3])
let ressources: Resource<CurrencyModel> = Resource(quotes: currencyModel,
                                                   success: true,
                                                   terms: "terms",
                                                   privacy: "privacy",
                                                   timestamp: 30,
                                                   source: "source")
do {
    let encoder = JSONEncoder()
    encoder.outputFormatting = .prettyPrinted
    let reversedJSONData = try encoder.encode(ressources)
    if let reversedJSONString = String(data: reversedJSONData, encoding: .utf8) {
        print(reversedJSONString)
    }
} catch {
    print("Error in reversing: \(error)")
}

这打印

{
  "success" : true,
  "quotes" : {
    "quotes" : {
      "Currency1" : 0.10000000000000001,
      "Currency2" : 0.20000000000000001,
      "Currency3" : 0.29999999999999999
    }
  },
  "terms" : "terms",
  "privacy" : "privacy",
  "timestamp" : 30,
  "source" : "source"
}

通过这种方式,您将看到使用当前代码应该看起来像 JSON 的内容。

请注意,如果有自定义初始化,您需要进行更改以反射(reflect)它。

关于ios - 如何快速传递关联类型中的 Codable 对象,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/58624387/

相关文章:

ios - 是否可以在iOS中检查用户是否给予(评分和评论)

ios - 在表格 View 中滚动后,选中标记会更改

swift - 使用 CoreMIDI 发送系统独有消息

swift - 多个 CoreData 实体的通用函数

xcode - swift : Auto Layout Issue

swift - 是否有 zip 函数来创建包含 2 个以上元素的元组?

ios - 在 objective-c 中追加数组并删除重复项而不更改顺序

ios - UICollectionView 滚动 SWIFT 滞后/缓慢

android - 有没有办法在 Android 或 iOS 库中的 worklight connect 方法调用中指定超时?

javascript - 是否可以配置 iOS 原生 HTML5 日期选择器?