swift - 在 Swift 5 中使用 Decodables 在一个页面上执行多个 API 请求
问题描述
我用来获取加载decodable
a 后需要点击的 URL 列表。TableView
这是我获取 URL 的结构:
struct CharactersUrls: Decodable {
let characters: [String]
}
struct Characters: Decodable {
let characters: [String]
}
struct CharacterInfo: Decodable {
let Id: Int
let name: String
let status: String
}
这是我的功能:
fileprivate func getCharactersUrls() {
let endpoint = "https://rickandmortyapi.com/api/episode/\(episodeID ?? "1")"
guard let url = URL(string: endpoint) else { return }
URLSession.shared.dataTask(with: url) {(data, response, error) in
guard let data = data else { return }
do {
let charactersUrls = try JSONDecoder().decode(CharactersUrls.self, from: data)
print("Characters URLS: \(charactersUrls)")
let endpoints = [charactersUrls]
print("Endpoints -> \(endpoints)")
} catch let jsonError {
print("Error Serializing JSON:", jsonError)
}
}.resume()
}
我在控制台中成功打印了 url:
Endpoints -> [Rick___Morty.CharactersUrls(characters: ["https://rickandmortyapi.com/api/character/1", "https://rickandmortyapi.com/api/character/2", "https://rickandmortyapi.com/api/character/38", "https://rickandmortyapi.com/api/character/87", "https://rickandmortyapi.com/api/character/338"])]
现在我需要点击每个 url 以从中获取id, name, status
并将它们加载到tableView
什么是最好的方法来做到这一点Decodable
呢?
解决方案
首先你的CharacterInfo
结构是错误的,id
是小写的。
要获取所有字符的信息,您需要第二个数据任务。要在所有任务完成时收到通知,请使用DispatchGroup
. 为方便起见,将status
其解码为枚举。
struct CharactersUrls: Decodable {
let characters: [URL]
}
enum Status : String, Decodable {
case dead = "Dead", alive = "Alive"
}
struct CharacterInfo: Decodable {
let id: Int
let name: String
let status: Status
}
var characterInfos = [CharacterInfo]()
fileprivate func getCharactersUrls() {
let endpoint = "https://rickandmortyapi.com/api/episode/\(episodeID ?? "1")"
guard let endPointURL = URL(string: endpoint) else { return }
let group = DispatchGroup()
let outertask = URLSession.shared.dataTask(with: endPointURL) { data, response, error in
guard let data = data else { print(error!); return }
do {
let charactersUrls = try JSONDecoder().decode(CharactersUrls.self, from: data)
print("Characters URLS: \(charactersUrls)")
for infoURL in charactersUrls.characters {
group.enter()
let innertask = URLSession.shared.dataTask(with: infoURL) { data, response, error in
defer{ group.leave() }
guard let data = data else { print(error!); return }
do {
let characterInfo = try JSONDecoder().decode(CharacterInfo.self, from: data)
characterInfos.append(characterInfo)
} catch {
print("Error Getting Info for \(infoURL):", error)
}
}
innertask.resume()
}
group.notify(queue: .main) {
print(characterInfos)
}
} catch {
print("Error Serializing JSON:", error)
}
}
outertask.resume()
}
要characterInfos
在表格视图中显示数组,有无数的教程和示例。
推荐阅读
- android - 使用 Jetpack 自定义实施操作项
- php - 如何使用登录和注册功能更改 laravel 8 中的身份验证表
- flutter - 带有 Flutter 的 Android 工作室。如何正确设置?
- flask - Google App Engine (GAE) 基本扩展后端实例服务一个请求并取消部署
- mysql - GROUP_CONCAT 多个字段在 ARRAY 中具有不同的分隔符
- macos - SwiftUI Image 不显示现有文件中的图像
- java - 如何调查 Apache Camel Route 上的数据?
- r - 如何根据 R 中另一个列表的内容将区域分配给一个列表?
- python - 可以使用 Python 相对导入以特定名称导入当前模块的 __init__ 文件吗?
- pip - pipenv 和 pip 之间的链接