RxSwift下UITableView两种不同高度cell仅显示最大高度问题求解
问题原因
- 你写的cell类型判断逻辑错误:
workoutsTableView.cellForRow(at: indexPath) == FutureSessionCell()是将当前indexPath的cell和新创建的FutureSessionCell实例做内存地址对比,永远返回false,所以所有场景都进入else分支返回390,这是所有cell都显示大高度的直接原因。 heightForRowAt的调用时机早于cell的渲染完成,此时调用cellForRow(at:)无法获取到正确的cell实例,还会触发heightForRowAt的循环调用,引发性能损耗甚至死循环。- 搭配RxSwift的
rx.items绑定数据源时,优先适配Rx的使用规范,不要混用传统代理的硬编码高度判断,避免逻辑割裂。
修复方案
方案1:自动高度适配(推荐)
如果你的两个cell内部已经通过AutoLayout将子控件撑满contentView的上下边缘,直接开启UITableView的自动高度即可,不需要手动判断返回高度:
- 在
viewDidLoad中添加以下配置:
// 开启自动高度 workoutsTableView.rowHeight = UITableView.automaticDimension // 设置预估高度,值接近两种cell的平均高度即可,用于提升滚动性能 workoutsTableView.estimatedRowHeight = 300
- 直接删除你当前实现的
heightForRowAt代理方法即可。
方案2:固定高度手动返回
如果业务需求必须使用固定高度,不要通过cell判断类型,直接通过数据源的属性判断即可:
你的cell类型由数据源的workout.createdByCoach字段决定,直接取对应indexPath的数据源字段判断即可,修改heightForRowAt逻辑:
extension CalendarVC: UITableViewDelegate { func tableView(_ tableView: UITableView, heightForRowAt indexPath: IndexPath) -> CGFloat { let currentWorkout = vm.workoutForOneDay.value[indexPath.row] return currentWorkout.createdByCoach ? 190 : 390 } }
同时需要将代理和Rx绑定,在bindTableViewWorkouts方法中添加代理绑定逻辑:
workoutsTableView.rx.setDelegate(self) .disposed(by: disposeBag)
内容的提问来源于stack exchange,提问作者Karl Mcgeough
相关产品推荐
相关产品推荐

