Swift 4 可解码 - 附加变量

Posted

技术标签:

【中文标题】Swift 4 可解码 - 附加变量【英文标题】:Swift 4 Decodable - Additional Variables 【发布时间】:2018-02-16 16:40:45 【问题描述】:

目前我还没有想出或能够在网上找到的东西。

有没有办法将附加字段添加到包含 JSON 数据中不存在的可解码协议的结构上?

举个简单的例子,假设我有一个这样构造的 json 对象数组

“名称”:“名称1”, “网址”:“www.google.com/randomImage”

但是说我想添加一个 UIImage 变量到包含可解码的结构中,例如

struct Example1: Decodable 
    var name: String?
    var url: String?
    var urlImage: UIImage? //To add later

有没有办法实现可解码协议以便从 JSON 中获取名称和 url,但允许我稍后添加 UIImage?

【问题讨论】:

@Rob:我不这么认为——因为UIImage 不是Decodable 它甚至不会合成协议一致性 【参考方案1】:

要排除urlImage,您必须手动符合Decodable,而不是让其要求被综合:

struct Example1 : Decodable  //(types should be capitalized)
    var name: String?
    var url: URL? //try the `URL` type! it's codable and much better than `String` for storing URLs
    var urlImage: UIImage? //not decoded

    private enum CodingKeys: String, CodingKey  case name, url  //this is usually synthesized, but we have to define it ourselves to exclude `urlImage`

在 Swift 4.1 之前,这仅在将 = nil 添加到 urlImage 时才有效,即使默认值 nil 通常假定为可选属性。

如果你想在初始化时为urlImage提供一个值,而不是使用= nil,你也可以手动定义初始化器:

    init(from decoder: Decoder) throws 
        let container = try decoder.container(keyedBy: CodingKeys.self)
        name = try container.decode(String.self, forKey: .name)
        url = try container.decode(URL.self, forKey: .url)
        urlImage = //whatever you want!
    

【讨论】:

编译器实际上可以为你合成init(from:)。您只需要说var urlImage: UIImage? = nil 即可满足其对CodingKeys 中未列出的属性的默认值的需求(为什么它不接受nil 的隐式默认值我不太确定) . 非常感谢!这有点奇怪,我想这也是我的问题。我将 nil 值分配给从 json 属性中排除的变量并不断抛出错误。 需要明确分配nil 是我现在正在修复的行为中的一个错误(实际上是疏忽)。将来应该不需要这样做。 这个问题现在在 Swift 4.1 中得到修复,你可以省略 = nil :) 在 Swift 5 中,这里需要 nil。此外,按照 cmets 中的建议将其设置为 nil 也不错,但是在解码后如何设置它而不自己实际编写 init(from:)?【参考方案2】:

实际上,我会让 urlImage 成为一个惰性变量。这样您就不必担心修改编码键。你所要做的就是写你的吸气剂,像这样......

struct Example1 : Decodable 

    var name : String?
    var url  : URL?    // Better than String

    lazy var urlImage: UIImage? = 
        // Put your image-loading code here using 'url'
    ()

【讨论】:

该解决方案的问题在于它仅适用于 var。如果我想做let example = ... 之类的事情,我将无法再访问 urlImage,因为示例对象现在是不可变的。 他的例子专门说'稍后添加'这就是我这样写的原因,但如果你希望它被视为'让',至少来自外界,只需使用@ 987654323@

以上是关于Swift 4 可解码 - 附加变量的主要内容,如果未能解决你的问题,请参考以下文章

带有可配置键的 Swift 4 JSON 解码

使用可选值 Swift 4 解码嵌套 JSON

JSON解码器Swift 4.0

如何在 Swift 4 中引用通用的可解码结构

如何在 Swift 4 的可解码协议中使用自定义键?

Swift 4 可解码的 json 数组