您的位置:首页 > 运维架构

RunLoop的应用场景---关于滑动tableView的时候NSTimer 暂停的问题

2017-03-22 15:06 323 查看
1.我们经常会在应用中看到tableView 的header 上是一个横向ScrollView,一般我们使用NSTimer,每隔几秒切换一张图片。可是当我们滑动tableView的时候,顶部的scollView并不会切换图片,这可怎么办呢?

2.界面上除了有tableView,还有显示倒计时的Label,当我们在滑动tableView时,倒计时就停止了,这又该怎么办呢?

场景中的代码实现

我们的定时器Timer是怎么写的呢?

一般的做法是,在
主线程
(可能是某控制器的viewDidLoad方法)中,创建Timer。
可能会有两种写法,但是都有上面的问题,下面先看下Timer的两种写法:

// 第一种写法

NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerUpdate) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

[timer fire];

// 第二种写法

[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerUpdate) userInfo:nil repeat

上面的两种写法其实是等价的。第二种写法,默认也是将timer添加到
NSDefaultRunLoopMode
下的,并且会自动fire。

然后,我们在滑动tableView的时候timerUpdate方法,并不会调用。
* 原因是啥呢?*

原因是当我们滑动scrollView时,主线程的RunLoop 会切换到
UITrackingRunLoopMode
这个Mode,执行的也是
UITrackingRunLoopMode
下的任务(Mode中的item),而timer 是添加在
NSDefaultRunLoopMode
下的,所以timer任务并不会执行,只有当
UITrackingRunLoopMode
的任务执行完毕,runloop切换到
NSDefaultRunLoopMode
后,才会继续执行timer。

* 要如何解决这一问题呢?*

解决方法很简单,我们只需要在添加timer 时,将mode 设置为
NSRunLoopCommonModes
即可。

- (void)timerTest

{

// 第一种写法

NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerUpdate) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

[timer fire];

// 第二种写法,因为是固定添加到defaultMode中,就不要用了
}

每一个线程都有一个与之关联的RunLoop,而每一个RunLoop可能会有多个Mode。CPU会在多个线程间切换来执行任务,呈现出多个线程同时执行的效果。执行的任务其实就是RunLoop去各个Mode里执行各个item。因为RunLoop是独立的两个,相互不会影响,所以在子线程添加timer,滑动视图时,timer能正常运行。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: