绑定Rx数据源的UITableView导航栏大标题异常缩小问题求助
问题:UITableView绑定Rx Driver后,大标题导航栏导致列表滚动异常
我遇到一个奇怪的问题:当使用设置了prefersLargeTitles = true的UITableViewController,并且把UITableView绑定到Rx的Driver数据源时,如果绑定和初始数据加载操作是在视图处于屏幕外时执行的(比如提前初始化了控制器但还没push到导航栈),当导航到这个视图时,列表会自动滚动到导航栏大标题变为“最小化”状态的位置。
我的代码结构大概是这样的,所有TableView配置和Rx绑定都在viewDidLoad里完成:
override func viewDidLoad() { super.viewDidLoad() setupTableView() bindToTableView() // ... } private func setupTableView() { tableView.register(cellType: Cell.self) tableView.tableFooterView = UIView() tableView.separatorStyle = .none // ... // 重置数据源和代理,交给RxCocoa接管 tableView.dataSource = nil tableView.delegate = nil tableView.rx.setDelegate(self) .disposed(by: bag) // ... } private func bindToTableView() { viewModel.modelDriver .drive(tableView.rx.items) { tableView, row, model in let indexPath = IndexPath(row: row, section: 0) let cell: Cell = tableView.dequeueReusableCell(for: indexPath) cell.prepare(with: model) return cell }.disposed(by: bag) }
这里说的“大标题最小化”,就是导航栏从大标题样式切换成紧凑的小标题样式的状态。有没有其他开发者遇到过这个问题?
已解决方案
后来发现这个问题并不是Rx本身导致的,正如@daniel-t指出的,问题出在prefersLargeTitles的设置时机上:
- 如果在
tableView.reloadData()(这里Rx的初始数据绑定会触发类似的加载操作)调用之前,没有设置prefersLargeTitles = true,那么TableView会按照非大标题模式来计算和调整滚动位置; - 之后再设置大标题属性,TableView不会自动重置滚动位置来适配新的、更高的导航栏区域,就会出现滚动异常的情况。
甚至尝试用.skipUntil(...viewWillAppear)这类方法延迟绑定也没用,因为绑定操作一旦执行,Rx就会触发初始更新,进而重新加载TableView,还是会踩同样的坑。
正确的做法是:确保在任何可能触发TableView数据加载的操作(包括Rx绑定)之前,先设置好prefersLargeTitles = true。比如可以把这个设置放到init方法里,或者在viewDidLoad的最开头就完成设置,再去做TableView配置和Rx绑定。
内容的提问来源于stack exchange,提问作者Alex Persian
相关产品推荐
相关产品推荐

