ios - 成功解析 JSON 后,应该存储 JSON 的数组为空
问题描述
var pokemons = [Pokemon]()
func loadJSON() {
let url = "https://pokeapi.co/api/v2/pokemon/"
guard let urlObj = URL(string: url) else { return }
URLSession.shared.dataTask(with: urlObj) {(data, response, error) in
guard let data = data else { return }
do {
let pokedex = try JSONDecoder().decode(Pokedex.self, from: data)
for pokemon in pokedex.results {
guard let jsonURL = pokemon.url else { return }
guard let newURL = URL(string: jsonURL) else { return }
URLSession.shared.dataTask(with: newURL) {(data, response, error) in
guard let data = data else { return }
do {
let load = try JSONDecoder().decode(Pokemon.self, from: data)
self.pokemons.append(load)
} catch let jsonErr {
print("Error serializing inner JSON:", jsonErr)
}
}.resume()
}
} catch let jsonErr{
print("Error serializing JSON: ", jsonErr)
}
}.resume()
}
这段代码编译并运行良好,但是当我之后检查它的大小时,数组 pokemons 返回的计数为 0。这很奇怪,因为如果我在 pokemons.append(load) 之后循环遍历数组,它会吐出一堆数据。就好像数据一旦超出 JSON 的范围就会丢失。我的数组是否需要通过引用或其他方式传递?我正在寻找数据并将其放入 UITableView,但到目前为止没有显示任何内容。
override func viewDidLoad() {
super.viewDidLoad()
navigationItem.title = "Pokemon"
navigationController?.navigationBar.prefersLargeTitles = true
loadJSON()
print(pokemons.count) //Prints 0
tableView.register(UITableViewCell.self, forCellReuseIdentifier: cellId)
}
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
let label = UILabel()
label.text = "By Id"
label.backgroundColor = UIColor.lightGray
return label
}
override func numberOfSections(in tableView: UITableView) -> Int {
return 1
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return pokemons.count
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: cellId, for: indexPath)
let name = pokemons[indexPath.row].name
cell.textLabel?.text = "\(name) Section:\(indexPath.section) Row:\(indexPath.row)"
return cell
}
解决方案
你要么需要
self.pokemons.append(load)
DispatchQueue.main.async {
self.tableView.reloadData()
}
或写一个完成
异步调用是不与函数编写代码串联的东西,而是异步运行直到它完成然后它通知它的回调,并且在你的代码中,异步方法是URLSession.shared.dataTask
在后台线程中运行的(这就是为什么你必须在DispatchQueue.main.async
里面插入它刷新 UI ) 并将串行执行留在主线程,以确保您可以阻塞主线程,直到使用类似Data(contentsOf:url)
而不是的方法返回响应,URLSession.shared.dataTask
但这不是一个好主意
推荐阅读
- chef-infra - 刀:找不到命令
- python - 从列表中创建多个复选框并获取所有值
- powershell - PowerShell 脚本不会按顺序运行
- grails - com.nimbusds.jose.JOSEException:不支持的 JWS 算法 RS256,在使用 Auth0 令牌时必须是 HS256、HS384 或 HS512
- jquery - jQuery将单独的对象水平滚动在一起
- powershell - 在 Powershell 中将用户移动到禁用的 OU
- swift - 获取base64Encoded图像的真实尺寸
- postgresql - 如何从 csv 复制到 postgresql 表并忽略没有标题的列
- node.js - 将图像附加到 Messenger 中的 Facebook 登录按钮
- php - 电子邮件表格写入 .xlsx 而不是 .xls