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

解决RxDataSources中“Requested the number of rows for section (-1)”崩溃问题

问题解决方案

针对你遇到的RxTableViewSectionedReloadDataSource结合UITableView时的崩溃问题,以下是具体的解决思路和代码实现:

核心崩溃原因

该崩溃本质是UITableView内部状态与数据源不一致,当数据源为空或快速更新时,UITableView可能尝试访问索引为-1的分区(超出合法范围),触发系统断言。


具体解决步骤

1. 强制保证数据源分区数组非空

当原始数据为空时,返回一个包含空items的占位分区,彻底避免UITableView处理空分区数组的边界异常:

// 假设你的分区模型为CustomSection
func convertToSections(from rawData: [YourItemModel]) -> [CustomSection] {
    guard !rawData.isEmpty else {
        // 返回占位分区,模型和样式可根据需求调整
        return [CustomSection(headerTitle: "", items: [])]
    }
    // 正常的分区转换逻辑
    return yourNormalSectionTransformLogic(rawData)
}

2. 过滤重复/频繁的数据源更新

针对用户快速点击标签的场景,用RxSwift操作符过滤无效更新,避免UITableView状态混乱:

// 假设你的数据源Observable为dataStream
dataStream
    // 过滤完全相同的数据源更新,避免重复刷新
    .distinctUntilChanged { oldSections, newSections in
        guard oldSections.count == newSections.count else { return false }
        return zip(oldSections, newSections).allSatisfy { $0 == $1 }
    }
    // 防抖处理,避免短时间内多次触发更新(300ms可根据需求调整)
    .debounce(.milliseconds(300), scheduler: MainScheduler.instance)
    .bind(to: tableView.rx.items(dataSource: yourDataSource))
    .disposed(by: disposeBag)

3. 重写数据源的分区/行数校验逻辑

直接在RxTableViewSectionedReloadDataSource中重写分区和行数的计算方法,强制保证索引合法:

let dataSource = RxTableViewSectionedReloadDataSource<CustomSection>(
    configureCell: { ds, tv, ip, item in
        // 你的Cell配置逻辑
        return yourConfiguredCell
    }
)

// 强制分区数至少为1
dataSource.numberOfSections = { dataSource in
    max(dataSource.sectionModels.count, 1)
}

// 确保分区索引永远在合法范围内
dataSource.numberOfRowsInSection = { dataSource, section in
    let safeSection = max(min(section, dataSource.sectionModels.count - 1), 0)
    return dataSource.sectionModels[safeSection].items.count
}

4. 确保所有UI更新在主线程执行

即使RxSwift默认绑定到主线程,也显式指定线程,避免后台线程更新导致的时序问题:

dataStream
    .observe(on: MainScheduler.instance)
    .bind(to: tableView.rx.items(dataSource: yourDataSource))
    .disposed(by: disposeBag)

5. 检查自定义UITableView代理方法的边界处理

如果你手动实现了heightForRowAt、viewForHeaderInSection等代理方法,必须添加索引安全校验:

tableView.rx.heightForRowAt
    .subscribe(onNext: { [weak self] indexPath in
        guard let self = self,
              indexPath.section < self.dataSource.sectionModels.count,
              indexPath.row < self.dataSource.sectionModels[indexPath.section].items.count else {
            return 44 // 返回默认行高
        }
        // 正常计算行高逻辑
    })
    .disposed(by: disposeBag)

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.06.20 09:57:11