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

UITableView数据填充异常问题排查及优化方案咨询

问题分析与解决方案

嘿,我立刻就发现你代码里的问题啦!咱们一步步来拆解:

一、Bug根源:索引传递错误

你第三个VC(ProvinceVC)的provinceData是一个一维数组,按「欧洲→亚洲→非洲…」的顺序存放了所有国家的拆分片段。但从第二个VC(CountryVC)跳转时,你传递的indexPath.row是当前大洲内的局部索引——比如亚洲第一个国家Thailand在亚洲数组里是索引0,但在全局国家列表里是第5个(索引5)。这就导致你选其他大洲的国家时,第三个VC始终拿的是欧洲对应局部索引的拆分数据,自然就错了!

二、快速修复方案

只需要修改CountryVC的didSelectRowAt方法,计算全局国家索引再传递给ProvinceVC:

func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    // 计算全局索引:累加当前大洲之前所有大洲的国家数量 + 当前大洲内的索引
    var globalCountryIndex = 0
    for i in 0..<continentIndex {
        globalCountryIndex += countryData[i].count
    }
    globalCountryIndex += indexPath.row
    
    let provinceVC = ProvinceVC()
    provinceVC.customInit(countryIndex: globalCountryIndex, title: countryData[continentIndex][indexPath.row])
    self.navigationController?.pushViewController(provinceVC, animated: true)
    tableView.deselectRow(at: indexPath, animated: true)
}

这样传递过去的就是正确的全局索引,第三个VC就能匹配到对应国家的拆分数据了。

三、更优实现方式:用结构化数据替代独立数组

当前用多个独立数组(continentData/countryData/provinceData)来维护层级数据,很容易出现索引不匹配的问题,而且后续新增/修改数据时需要同步修改多个数组,维护成本极高。推荐用结构体组织层级数据,直接传递数据对象而非索引:

1. 定义数据模型

// 定义大洲、国家的结构化数据
struct Continent {
    let name: String
    let countries: [Country]
}

struct Country {
    let name: String
    let nameSegments: [String] // 对应原有的拆分片段
}

2. 第一个VC(大洲列表)修改

class ViewController: UIViewController, UITableViewDelegate, UITableViewDataSource {
    @IBOutlet weak var TableView: UITableView!
    // 初始化完整的层级数据
    let continents: [Continent] = [
        Continent(name: "Europe", countries: [
            Country(name: "Germany", nameSegments: ["Ger","ma","ny"]),
            Country(name: "France", nameSegments: ["Fr","a","nce"]),
            Country(name: "Italy", nameSegments: ["Ita","ly"]),
            Country(name: "Spain", nameSegments: ["Spa","in"]),
            Country(name: "Sweden", nameSegments: ["Swe","den"])
        ]),
        Continent(name: "Asia", countries: [
            Country(name: "Thailand", nameSegments: ["Tha","il","and"]),
            Country(name: "Singapore", nameSegments: ["Si","nga","po","re"]),
            Country(name: "China", nameSegments: ["Chi","na"]),
            Country(name: "Philippines", nameSegments: ["Phi","li","pp","ines"]),
            Country(name: "Japan", nameSegments: ["Ja","pan"])
        ]),
        // 其他大洲数据以此类推...
        Continent(name: "Africa", countries: [
            Country(name: "Zambia", nameSegments: ["Za","mb","ia"]),
            Country(name: "Egypt", nameSegments: ["Egy","pt"]),
            Country(name: "Kenya", nameSegments: ["Ke","nya"]),
            Country(name: "Nigeria", nameSegments: ["Ni","ge","ria"]),
            Country(name: "Morocco", nameSegments: ["Mo","ro","cco"])
        ]),
        Continent(name: "North America", countries: [
            Country(name: "Canada", nameSegments: ["Ca","na","da"]),
            Country(name: "USA", nameSegments: ["USA"]),
            Country(name: "Mexico", nameSegments: ["Me","xi","co"]),
            Country(name: "Jamaica", nameSegments: ["Ja","ma","ica"]),
            Country(name: "Dominica", nameSegments: ["Do","mi","ni","ca"])
        ]),
        Continent(name: "South America", countries: [
            Country(name: "Argentina", nameSegments: ["Ar","ge","nt","ina"]),
            Country(name: "Peru", nameSegments: ["Pe","ru"]),
            Country(name: "Colombia", nameSegments: ["Co","lo","mb","ia"]),
            Country(name: "Brazil", nameSegments: ["Bra","zil"]),
            Country(name: "Chile", nameSegments: ["Chi","le"])
        ]),
        Continent(name: "Australia", countries: [
            Country(name: "Australia", nameSegments: ["Au","st","ra","lia"]),
            Country(name: "New Zealand", nameSegments: ["New","Zea","la","nd"]),
            Country(name: "Fiji", nameSegments: ["Fi","ji"]),
            Country(name: "Solomon Islands", nameSegments: ["So","lo","mon","Is","la","nds"])
        ])
    ]
    
    override func viewDidLoad() {
        super.viewDidLoad()
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return continents.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "continentCell", for: indexPath)
        cell.textLabel?.text = continents[indexPath.row].name
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let selectedContinent = continents[indexPath.row]
        let countryVC = CountryVC()
        countryVC.continent = selectedContinent
        countryVC.title = selectedContinent.name
        self.navigationController?.pushViewController(countryVC, animated: true)
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

3. 第二个VC(国家列表)修改

class CountryVC: UIViewController,UITableViewDataSource, UITableViewDelegate {
    @IBOutlet weak var tableView: UITableView!
    // 直接接收完整的大洲数据对象
    var continent: Continent!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.dataSource = self
        self.tableView.delegate = self
        let nib = UINib(nibName:"CountryCell", bundle: nil)
        tableView.register(nib, forCellReuseIdentifier: "countryCell")
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return continent.countries.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "countryCell", for: indexPath) as! CountryCell
        cell.textLabel?.text = continent.countries[indexPath.row].name
        return cell
    }
    
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let selectedCountry = continent.countries[indexPath.row]
        let provinceVC = ProvinceVC()
        provinceVC.country = selectedCountry
        provinceVC.title = selectedCountry.name
        self.navigationController?.pushViewController(provinceVC, animated: true)
        tableView.deselectRow(at: indexPath, animated: true)
    }
}

4. 第三个VC(拆分片段列表)修改

class ProvinceVC: UIViewController, UITableViewDataSource,UITableViewDelegate {
    @IBOutlet weak var tableView: UITableView!
    // 直接接收完整的国家数据对象
    var country: Country!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        self.tableView.dataSource = self
        self.tableView.delegate = self
        let nib = UINib(nibName:"ProvinceCell", bundle: nil)
        tableView.register(nib, forCellReuseIdentifier: "provinceCell")
    }
    
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return country.nameSegments.count
    }
    
    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell = tableView.dequeueReusableCell(withIdentifier: "provinceCell", for: indexPath) as! ProvinceCell
        cell.textLabel?.text = country.nameSegments[indexPath.row]
        return cell
    }
}

这种实现方式的优势:

  • 数据结构清晰:大洲→国家→拆分片段的层级关系一目了然,彻底避免索引不匹配的问题
  • 维护成本低:新增/修改数据时只需要修改一处模型数据,不用同步多个数组
  • 代码可读性高:直接传递数据对象,逻辑更直观,后续调试也更方便

内容的提问来源于stack exchange,提问作者The_Ogre

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:16:00