iOS开发:点击TableView后匹配ID拉取宝可梦详情数据方案咨询
解决方案
1. 完善DetailViewController
给详情页添加接收宝可梦ID的属性,同时实现数据拉取与UI填充逻辑:
class DetailViewController: UIViewController { @IBOutlet weak var nameLabel: UILabel! @IBOutlet weak var detailImageView: UIImageView! @IBOutlet weak var heightLabel: UILabel! @IBOutlet weak var abilitiesLabel: UILabel! @IBOutlet weak var statsLabel: UILabel! // 接收主页面传递的宝可梦ID var pokemonID: String? override func viewDidLoad() { super.viewDidLoad() // 页面加载后立即拉取详情数据 loadPokemonDetail() } // 拉取宝可梦详情数据 private func loadPokemonDetail() { guard let id = pokemonID else { return } PokeAPIService.shared.getPokemon(by: id) { [weak self] pokemon in DispatchQueue.main.async { self?.updateUI(with: pokemon) } } } // 填充页面UI private func updateUI(with pokemon: GetPokemonResponse) { // 名称(首字母大写优化) nameLabel.text = pokemon.name?.capitalized // 身高(PokeAPI返回单位为分米,转为米显示) if let height = pokemon.height { heightLabel.text = "身高:\(height / 10.0)m" } // 技能:将数组转为逗号分隔的字符串 let abilityNames = pokemon.abilities?.compactMap { $0.ability?.name?.capitalized }.joined(separator: ", ") ?? "无" abilitiesLabel.text = "技能:\(abilityNames)" // 属性:将属性与数值拼接为多行文本 let statTexts = pokemon.stats?.compactMap { stat in guard let statName = stat.stat?.name?.capitalized, let baseStat = stat.baseStat else { return nil } return "\(statName):\(baseStat)" }.joined(separator: "\n") ?? "无" statsLabel.text = "属性:\n\(statTexts)" // 加载官方 artwork 图片 if let id = pokemonID, let imageURL = PokeAPIService.shared.getPokemonOfficialArtwork(id: id) { detailImageView.loadImage(from: imageURL) } } } // UIImageView图片加载扩展(可复用已实现的方法) extension UIImageView { func loadImage(from url: URL) { URLSession.shared.dataTask(with: url) { [weak self] data, _, error in guard let data = data, error == nil else { return } DispatchQueue.main.async { self?.image = UIImage(data: data) } }.resume() } }
2. 实现MainViewController的点击跳转逻辑
完善didSelectRowAt方法,传递ID并跳转到详情页:
extension MainViewController: UITableViewDelegate, UITableViewDataSource { // 保留原有其他方法... func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) { // 取消cell选中状态 tableView.deselectRow(at: indexPath, animated: true) // 获取选中宝可梦的ID let selectedPokemon = pokemons[indexPath.row] let pokemonID = selectedPokemon.pokemonID // 代码跳转详情页(需确保Storyboard中详情页的identifier为"DetailViewController") if let detailVC = storyboard?.instantiateViewController(withIdentifier: "DetailViewController") as? DetailViewController { detailVC.pokemonID = pokemonID navigationController?.pushViewController(detailVC, animated: true) } // 若使用Storyboard Segue跳转(提前拖拽Segue并设置ID为"showDetail"),可替换为以下代码: // performSegue(withIdentifier: "showDetail", sender: pokemonID) } // Segue跳转时的传值方法(若使用Segue则取消注释) // override func prepare(for segue: UIStoryboardSegue, sender: Any?) { // if segue.identifier == "showDetail", let detailVC = segue.destination as? DetailViewController, let pokemonID = sender as? String { // detailVC.pokemonID = pokemonID // } // } }
3. 关键注意事项
- 确保Storyboard中
DetailViewController的Storyboard ID与代码中使用的标识符一致。 - 确认
GetPokemonsResponse.Pokemon模型的pokemonID属性已正确从API返回的url字段中提取(例如从https://pokeapi.co/api/v2/pokemon/1/截取1作为ID)。 - 所有可选值处理需做好判空,避免空指针崩溃。
内容的提问来源于stack exchange,提问作者LordGrim
相关产品推荐
相关产品推荐

