Swift:为什么 JSONDecoder(Codable/Decodable)不调用结构体的 init() 方法?



我觉得我一定缺少一些东西。斯威夫特 5.1.

我有以下设置为Decodable struct,以便我可以解析外部 JSON URL:

struct ReleaseGroup: Decodable, Identifiable {
  let id: Int
  let externalServiceID: String
  let title: String
  let externalServiceImageURL: URL
  let type: String
  var image: UIImage?
  private enum CodingKeys: String, CodingKey {
    case id
    case externalServiceID = "external_service_id"
    case title
    case externalServiceImageURL = "external_service_image_url"
    case type
  }
  // do I have to do this just because UIImage is an optional?
  init(id: Int, externalServiceID: String, title: String, externalServiceImageURL: URL, type: String) {
    let url = URL(string: "https://someurl.com/some-image.jpeg")
    let data = try? Data(contentsOf: url!)
    self.image = UIImage(data: data!)
    self.id = id
    self.externalServiceID = externalServiceID
    self.title = title
    self.type = type
    self.externalServiceImageURL = externalServiceImageURL
  }
}

我还在其他地方定义了这段代码,它负责从 API 调用实际创建实例:

init() {
  guard let url = URL(string: "http://127.0.0.1:8000/api/releases/") else { return }
  URLSession.shared.dataTask(with: url) { (data, _, _) in
    guard let data = data else { return }
    let releaseGroups = try! JSONDecoder().decode([ReleaseGroup].self, from: data)
    DispatchQueue.main.async {
        self.releaseGroups = releaseGroups
      }
    }
    }.resume()
}

但是,上面没有调用ReleaseGroupinit()方法,我认为在创建ReleaseGroup实例时都可以调用该方法。

如果我显式创建它们,它可以工作:

for releaseGroup in releaseGroups {
          let rg = ReleaseGroup.init(id: releaseGroup.id, externalServiceID: releaseGroup.externalServiceID, title: releaseGroup.title, externalServiceImageURL: releaseGroup.externalServiceImageURL, type: releaseGroup.type)
            self.releaseGroups.append(rg)
        }

解码器将调用init(from:),这是Decodable协议的一部分。这个 init 是合成的,所以如果你需要对你的对象构造做一些特别的事情,这是你需要自己实现的 init 方法。

有关更多信息,请参阅苹果的这篇文章

最新更新