You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

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

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.07.27 08:49:56