前言:上一回实现了轮播器的自动滚动,但是有两个需要处理的bug.
1.增加需求:当用手拖拽控制轮播器的时候,停止自动滚动.
2.当同一个页面中有tableView,textView或scrollview时,拖拽这些控件时:轮播器会停止自动轮播,卡住;当松开这些控件时:轮播器先快速轮播,把卡住的时间补回来,再恢复正常.
原因:界面的控件都是主线程创建的,和用户的操作也都是在主线程中处理的. 当用户拖拽另外的控件时,主线程就忙着处理这些拖拽行为,就不能同时处理轮播器的滚动事件了.
解决问题1:
1>.当多出用到同样的代码时,提取成一个方法:本demo中有两处: 添加定时器,移除定时器
// 添加定时器 - (void)addTimer { self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(nextImage) userInfo:nil repeats:YES]; // 解决拖动其他控件的时候,图片轮播器不能响应的问题 // 获取当前主线程的消息循环,把self.timer加到主运行循环中.NSRunLoopCommonModes可以同时处理多个事件.
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; } // 移除定时器 - (void)removeTimer { [self.timer invalidate]; // 所以清空self.timer self.timer = nil; }
2>使用代理方法解决问题1. 当即将拖拽时,移除定时器. 完成拖拽是启动定时器.
#pragma mark - 代理方法 - (void)scrollViewWillBeginDragging:(UIScrollView *)scrollView { // 1.停止定时器,定时器一旦停止,就不能重用了 [self removeTimer]; } - (void)scrollViewDidEndDragging:(UIScrollView *)scrollView willDecelerate:(BOOL)decelerate { // 启动定时器 [self addTimer]; }
解决问题2:
方法1>多线程处理.这里不行. 在ios中处理UI界面的事件,只能在主线程中执行,不能用其他的线程来处理.如果多个线程来处理UI界面.很可能造成混乱冲突.例如UI显示一份数据.要保证同一时间,只有一个人可以修改这份数据. 如果多线程的话就可以有多个人同一时间进行操作.就会冲突.
方法2>提高Scrollview拖拽事件的优先级,就是让主线程同时处理这两个事件.
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];// 获取当前主线程的消息循环,把self.timer加到主运行循环中.NSRunLoopCommonModes可以同时处理多个事件.