UITableView搜索刷新报错:尝试插入第3节但更新后仅3节求助
解决UITableView刷新时的Section越界错误
这个错误attempt to insert section 3 but there are only 3 sections after the update本质是你的数据源(countDic)和UITableView预期的section数量不一致导致的,咱们一步步拆解问题并修复:
问题根源分析
- 当搜索文本清空时,你直接调用了
self.countDic.removeAll(),这会把固定的0、1号section的计数也删掉,后续重建时如果没有正确恢复这两个section,tableView的section数量就会和预期不符。 - 你刷新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
相关产品推荐
相关产品推荐

