我觉得我一定缺少一些东西。斯威夫特 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()
}
但是,上面没有调用ReleaseGroup
的init()
方法,我认为在创建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 方法。
有关更多信息,请参阅苹果的这篇文章