如何检测点击TabBar切换控制器时ScrollView的滚动停止时机?
解决TabBar切换时UITableView滚动停止事件未触发的问题
当快速滑动UITableView的同时切换TabBarItem,当前ViewController的view会被移出视图层级,导致UIScrollView的三个停止代理方法都无法触发。可以通过以下几种方式处理:
方案1:监听TabBar切换通知
在包含UITableView的子ViewController中,监听TabBarController的切换通知,在切换时检查滚动状态:
- (void)viewDidLoad { [super viewDidLoad]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(onTabBarSwitched:) name:UITabBarControllerDidSelectViewControllerNotification object:nil]; } - (void)onTabBarSwitched:(NSNotification *)note { UITabBarController *tabBarVC = (UITabBarController *)note.object; // 确认当前VC是被切换走的那个 if (tabBarVC.selectedViewController != self) { [self handleScrollIfNeeded]; } } - (void)handleScrollIfNeeded { if (self.tableView.isDragging || self.tableView.isDecelerating) { // 立即终止滚动 [self.tableView setContentOffset:self.tableView.contentOffset animated:NO]; // 执行滚动停止后的逻辑 [self scrollViewStopped]; } } - (void)scrollViewStopped { // 这里放原本在三个代理方法里的停止处理逻辑 } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; }
方案2:利用ViewController生命周期方法
在子ViewController的viewWillDisappear:中检查滚动状态,因为切换TabBar时当前VC的view会进入消失流程:
- (void)viewWillDisappear:(BOOL)animated { [super viewWillDisappear:animated]; [self handleScrollIfNeeded]; } - (void)handleScrollIfNeeded { if (self.tableView.isDragging || self.tableView.isDecelerating) { [self.tableView setContentOffset:self.tableView.contentOffset animated:NO]; [self scrollViewStopped]; } } - (void)scrollViewStopped { // 统一的滚动停止处理逻辑 }
方案3:监听ScrollView的窗口移除事件
重写UIScrollView的代理方法scrollViewWillMoveToWindow:,当ScrollView即将从窗口移除时检查状态:
- (void)scrollViewWillMoveToWindow:(UIWindow *)newWindow { [super scrollViewWillMoveToWindow:newWindow]; // 当scrollView即将离开窗口时 if (newWindow == nil && (self.tableView.isDragging || self.tableView.isDecelerating)) { [self scrollViewStopped]; } }
注意事项
- 将滚动停止的逻辑抽成公共方法
scrollViewStopped,避免在多个地方重复代码,同时保证逻辑一致性。 - 使用
setContentOffset:animated:NO可以立即终止滚动,确保状态同步,避免后续出现异常。
内容的提问来源于stack exchange,提问作者ming
相关产品推荐
相关产品推荐

