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

如何在静态UITableView中嵌入动态UITableView?解决NSRangeException报错

问题

在一个使用静态单元格的UITableViewController界面中,所有UI组件(标签、图片、按钮等)都放在静态单元格内。现在需要在其中一个静态单元格里嵌入一个高度不固定、行数动态变化的UITableView(tag设为2)。编写的代理与数据源代码如下:

override func numberOfSections(in tableView: UITableView) -> Int {
        return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    if tableView.tag == 2 {
        return 3
    }
    return super.tableView(tableView, numberOfRowsInSection: section)
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    if tableView.tag == 2 {
        let cell = (tableView.dequeueReusableCell(withIdentifier: Constant.ReuseIdentifiers.offersViewCell) as? OffersTableViewCell)!
        return cell
    }
    return super.tableView(tableView, cellForRowAt: indexPath)
}

override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
    if tableView.tag == 2 {
        // Do something when a dynamic row is selected
    } else {
        super.tableView(tableView, didSelectRowAt: indexPath)
    }
}

运行应用进入该界面时,抛出错误:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSSingleObjectArrayI objectAtIndex:]: index 1 beyond bounds [0 .. 0]'

此前无动态UITableView时无需实现这些方法,问题应该出在代理/数据源方法的区分上,请问如何正确区分静态与动态UITableView的代理/数据源方法,实现该功能?(后续再处理动态表高度自适应)

解决方案

出现这个错误的核心原因是:你重写了numberOfSections(in:)方法并固定返回1,覆盖了静态表格在Storyboard中的原始分区配置,导致静态表格的数据源逻辑混乱,引发数组越界。正确的做法是仅针对动态子表格处理代理/数据源逻辑,静态表格的所有方法完全交给父类处理,具体修正步骤如下:

  1. 删除重写的numberOfSections(in:)方法
    静态表格的分区数由Storyboard中的可视化配置决定,不要通过代码强行覆盖返回固定值,否则会破坏静态表格的原有数据源结构。

  2. 完善动态表格的代理/数据源区分逻辑
    确保所有代理/数据源方法都先判断是否是动态子表格(tag=2),只有符合条件时才自定义处理,否则直接调用父类方法:

    override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        // 仅处理动态子表格,静态表格逻辑交给父类
        guard tableView.tag == 2 else {
            return super.tableView(tableView, numberOfRowsInSection: section)
        }
        return 3 // 动态表格的行数,可根据实际数据动态调整
    }
    
    override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        guard tableView.tag == 2 else {
            return super.tableView(tableView, cellForRowAt: indexPath)
        }
        // 用可选绑定替代强制解包,避免cell复用失败时崩溃
        guard let cell = tableView.dequeueReusableCell(withIdentifier: Constant.ReuseIdentifiers.offersViewCell, for: indexPath) as? OffersTableViewCell else {
            return UITableViewCell()
        }
        // 在这里配置动态表格cell的内容
        return cell
    }
    
    override func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        guard tableView.tag == 2 else {
            super.tableView(tableView, didSelectRowAt: indexPath)
            return
        }
        // 动态表格行的选中逻辑
    }
    
  3. 额外注意事项

    • 确保动态子表格的delegate和dataSource已设置为当前UITableViewController,保证代理方法能被正确回调。
    • 不要在静态表格的代理方法中修改其原有配置,静态表格的所有行为依赖Storyboard中的可视化设置,代码层面尽量不要干预。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.18 17:35:08