使用Ramotion folding-cell库搜索过滤后点击行触发行数异常错误
解决Folding Cell过滤后reloadData的行数不匹配错误
这个问题我之前在使用Ramotion的Folding Cell库时也碰到过——核心原因是Folding Cell内部维护了自己的状态(比如展开单元格的记录、行高缓存等),你只修改了外部的数据源和硬编码的kRowsCount,但库内部的状态没同步更新,导致TableView刷新时出现预期行数和实际内部状态不匹配的冲突。
下面是具体的解决步骤,亲测有效:
1. 抛弃硬编码的行数常量,以数据源为唯一可信来源
首先删掉kRowsCount这种硬编码的行数定义,所有和行数相关的地方直接用过滤后的数据源count。比如在TableView的数据源方法里:
func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return filteredData.count // 直接返回过滤后的数据源数量 }
硬编码的数值很容易和实际数据源脱节,这是最容易踩的坑。
2. 过滤前重置Folding Cell的展开状态
Folding Cell会记录当前展开的单元格位置,过滤后原来的展开行可能已经不在新的数据源里了,必须先把这些状态清空:
func filterData(with searchText: String) { // 1. 先折叠所有展开的单元格 if let expandedIndexPath = tableView.indexPathForSelectedRow { if let foldingCell = tableView.cellForRow(at: expandedIndexPath) as? FoldingCell { foldingCell.fold(animated: false) // 无动画折叠,避免视觉错乱 } tableView.deselectRow(at: expandedIndexPath, animated: false) } // 2. 过滤数据源 filteredData = originalData.filter { $0.title.contains(searchText) } // 3. 刷新表格 tableView.reloadData() }
如果你的Folding Cell版本里有专门维护展开状态的属性(比如expandedIndices数组),记得也要清空它:
// 若存在该属性,添加这行 foldingCell.expandedIndices.removeAll()
3. 确保行高方法和数据源同步
检查tableView(_:heightForRowAt:)方法,确保它也是基于过滤后的数据源返回行高,而不是依赖旧的状态:
func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { // 确保indexPath在filteredData的范围内(避免越界) guard indexPath.row < filteredData.count else { return 0 } // 根据Folding Cell的状态返回对应行高 return isCellExpanded(at: indexPath) ? expandedHeight : foldedHeight }
为什么会出现这个错误?
Folding Cell为了实现流畅的折叠/展开动画,会在内部缓存展开单元格的位置、行高等状态。当你直接修改行数常量但没重置这些内部状态时,库仍然认为表格有11行,但TableView根据数据源只渲染3行,两者的状态不一致就会触发系统的行数校验错误。
内容的提问来源于stack exchange,提问作者 coinhndp
相关产品推荐
相关产品推荐

