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

UITableView搜索刷新报错:尝试插入第3节但更新后仅3节求助

解决UITableView刷新时的Section越界错误

这个错误attempt to insert section 3 but there are only 3 sections after the update本质是你的数据源(countDic)和UITableView预期的section数量不一致导致的,咱们一步步拆解问题并修复:

问题根源分析

  1. 当搜索文本清空时,你直接调用了self.countDic.removeAll(),这会把固定的0、1号section的计数也删掉,后续重建时如果没有正确恢复这两个section,tableView的section数量就会和预期不符。
  2. 你刷新section时用的IndexSet(integersIn: 2..<self.TblView.numberOfSections)是基于刷新前的tableView section数量,但此时countDic已经被修改,两者的section数量不同步,就会触发越界。

分步解决方案

1. 重构countDic的重置逻辑

无论搜索状态如何,都要保留固定的0、1号section的计数,不能直接清空整个字典。修改搜索清空时的代码:

if FilterStr == "" {
    // 只重置动态section,保留固定section的计数
    let fixedKeys = ["0", "1"]
    let dynamicKeys = countDic.keys.filter { !fixedKeys.contains($0) }
    dynamicKeys.forEach { countDic.removeValue(forKey: $0) }
    FilterData.removeAll()
    // 重新加载原始动态section的计数
    for i in 0..<arra1.count {
        self.countDic.updateValue(array.count, forKey: "\(i + 2)")
    }
} else {
    // 搜索状态下,先保留固定section的计数,再重建动态section
    let fixedCounts = [
        "0": countDic["0"]!,
        "1": countDic["1"]!
    ]
    countDic.removeAll()
    // 恢复固定section
    fixedCounts.forEach { countDic.updateValue($0.value, forKey: $0.key) }
    FilterData.removeAll()
    
    let arr : [Today_ActivityModel] = (Today_Activity_Data as NSArray).filtered(using: namesBeginningWithLetterPredicate.withSubstitutionVariables(["letter": FilterStr])) as! [Today_ActivityModel]
    if !arr.isEmpty {
        // 调用分组方法填充动态section的计数
        self.GetRecordsCityWiseFilter(ArrayList: arr )
    } else {
        // 搜索无结果时,仅保留固定的2个section,不添加动态section
    }
}

2. 修正刷新时的IndexSet计算

刷新section时,应该基于更新后的countDic的section数量,而不是刷新前的tableView数量:

DispatchQueue.main.async {
    UIView.performWithoutAnimation {
        // 动态section的范围是2到countDic.count - 1
        let indexSet = IndexSet(integersIn: 2..<self.countDic.count)
        self.TblView.reloadSections(indexSet, with: .bottom)
    }
}

3. 确保GetRecordsCityWiseFilter方法的正确性

你的代码里注释掉了GetRecordsCityWiseFilter,这个方法必须正确填充动态section的计数到countDic中,且section编号从2开始递增。示例实现:

func GetRecordsCityWiseFilter(ArrayList: [Today_ActivityModel]) {
    // 示例:按某种规则(如城市)分组生成动态section
    let groupedData = Dictionary(grouping: ArrayList) { $0.city }
    for (index, group) in groupedData.values.enumerated() {
        let sectionKey = "\(index + 2)"
        countDic.updateValue(group.count, forKey: sectionKey)
    }
}

额外注意事项

  • 永远保证numberOfSections返回的是countDic.count,numberOfRowsInSection返回对应section的计数,这两个代理方法是tableView的核心数据源,必须和countDic完全同步。
  • 避免在数据源未完全准备好时调用刷新,比如搜索结果处理完成后,确认countDic已经正确填充所有section(固定+动态)再执行reload。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.05.15 07:20:59