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

同一UIViewController配置两个UITableView,同时调用reloadData报空解包错误

问题核心根源

你的崩溃是由几个明显的配置错误导致的:

  • UITableView 的数据源、代理方法签名是系统固定的,不存在以 tableView1(...) 开头的回调方法,你写的所有自定义命名的表格回调方法系统永远不会触发。两个表格绑定当前控制器作为代理后,所有的回调都会统一走系统约定的、以 tableView(_:...) 开头的方法,完全无法区分当前回调属于哪个表格。
  • 没有在现有数据源方法里做表格实例的区分判断,导致两个表格都在拿第一份数据源(numberRecordList)渲染:既会出现复用单元格时标识匹配错误触发强制解包崩溃,也会出现数据越界访问的nil问题。之前单独重载某一个表格时可以正常运行,是因为另一个表格没有触发重载流程,系统不会向它请求数据;当两个表格同时重载时,两个表格都会走到同一个tableView(_:...)方法里,强行拿第一个表格的单元格标识去第二个表格里复用,自然会触发解包nil的错误。
  • 附带代码笔误:原第二个数据源方法中定义的是countFinanceRecordList,判断时却引用了不存在的countSettingRecordList,因为这个方法从来没被系统调用,所以编译阶段没有暴露这个错误。
具体修复步骤
  • 彻底删除所有以tableView1(...)开头的自定义方法,所有表格的数据源、代理逻辑全部统一写在系统约定的tableView(_:...)签名方法中。
  • 在每个数据源、代理方法内部,通过方法传入的tableView参数和你控制器持有的两个表格实例做比对,分别返回对应表格需要的数据、配置。
  • 将所有*强制解包单元格的as!*替换为安全解包逻辑,避免单元格复用失败直接触发nil崩溃。
修复后的核心代码参考
// 控制器中持有的两个表格实例
private let numberRecordTableView = UITableView()
private let settingRecordTableView = UITableView()

// 统一的数据源方法:返回对应表格的行数
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if tableView == numberRecordTableView {
        return JSON_VDICheckFull.response?.dataItems?.numberRecordList?.count ?? 0
    } else if tableView == settingRecordTableView {
        return JSON_VDICheckFull.response?.dataItems?.settingRecordList?.count ?? 0
    }
    return 0
}

// 统一的估算行高方法
func tableView(_ tableView: UITableView, estimatedHeightForRowAt indexPath: IndexPath) -> CGFloat {
    if tableView == numberRecordTableView {
        return 30.0
    } else {
        return 110.0
    }
}

// 统一的单元格配置方法
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    // 配置第一个表格的单元格
    if tableView == numberRecordTableView {
        guard let cell = tableView.dequeueReusableCell(withIdentifier: "NumberRecordListCell", for: indexPath) as? NumberRecordListCell else {
            return UITableViewCell()
        }
        cell.setNeedsLayout()
        cell.layoutIfNeeded()
        cell.fieldDate.text = JSON_VDICheckFull.response?.dataItems?.numberRecordList?[indexPath.row].dateOfInformation ?? "---"
        cell.fieldSource.text = JSON_VDICheckFull.response?.dataItems?.numberRecordList?[indexPath.row].sourceOfInformation ?? "---"
        cell.fieldNumber.text = String(JSON_VDICheckFull.response?.dataItems?.numberRecordList?[indexPath.row].number ?? 0)
        cell.separatorInset = UIEdgeInsets.zero
        cell.layoutMargins = UIEdgeInsets.zero
        return cell
    }
    // 配置第二个表格的单元格
    guard let cell = tableView.dequeueReusableCell(withIdentifier: "SettingRecordListCell", for: indexPath) as? SettingRecordListCell else {
        return UITableViewCell()
    }
    cell.setNeedsLayout()
    cell.layoutIfNeeded()
    return cell
}
注意事项
  • 请确保两个表格在初始化时,分别注册了对应的单元格复用标识:numberRecordTableView.register(NumberRecordListCell.self, forCellReuseIdentifier: "NumberRecordListCell")、settingRecordTableView.register(SettingRecordListCell.self, forCellReuseIdentifier: "SettingRecordListCell"),避免复用单元格时返回nil。
  • 两个表格分别设置代理、数据源为当前控制器后,直接调用numberRecordTableView.reloadData()和settingRecordTableView.reloadData()即可正常触发对应的数据回调,不会再出现解包nil的崩溃。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.25 23:45:07