RunLoop与Timer的使用

Timer是Runloop的一个触发源,用Timer时, Timer默认添加到当前的Runloop中,也可以手动添加到自己新建的Runloop中。
* RunLoopMode工作模式有五种:
  * defaultRunLoopMode  --默认模式
  * UITrackingRunLoopMode  --界面跟踪模式
  * commonModes   --占位模式,可配置的通用模式
(这里只说这三个个)
<>发现问题:

当拖拽界面时,timer暂停运行,不拖拽时timer又恢复运行。

<>解决问题:
  • 第一种模式:defaultRunLoopMode设置后,只能在不拖拽当前的其他界面时timer会执行,一旦拖拽当前其他界面就立马转换到其他UI界面执行,因为UI级触摸优先级最高。
  • 第二种模式:UITrackingRunLoopMode设置后,只会在当前界面发生拖拽时也就是触摸事件时,timer会跟踪执行,当不拖拽触发时timer就不会执行。
  • 第三种模式:commonModes设置后,是结合上面的两者,当屏幕触发拖拽时和不出发拖拽时,timer都会执行。

这时候就应该使用Runloop的commonModes模式,能够让定时器在Runloop两种模式切换时也不受影响。

-->OC写法:

/** 创建timer */
NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        //需要执行的代码
 }];

/** 把timer手动添加到自己新建的Runloop中,添加模式为通用的占位模式 */
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

//暂停和开启timer

//暂停
timer.fireDate = NSDate.distantFuture;
//开启
timer.fireDate = NSDate.distantPast;

释放定时器

/** 不用的时候记得释放 */
    if (timer) {
        [timer invalidate];
        timer = nil;
    }

-->Swift写法:

/** 创建timer */
let timer = Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(timerAction), userInfo: nil, repeats: false)

/** 把timer手动添加到自己新建的Runloop中,添加模式为通用的占位模式 */
RunLoop.main.add(timer, forMode: .commonModes)

//暂停和开启timer

//暂停
timer.fireDate = Date.distantFuture
//开启
timer.fireDate = Date.distantPast

销毁定时器

/** 不用的时候记得释放 */
guard let aTimer = self.timer
     else{ return }
aTimer.invalidate()

需要注意的是,timer内尽量执行轻量级代码,不要执行耗时耗性能操作,不然当界面滚动的时候,仍然会出现卡顿的情况。

如果timer调用耗费时间的代码的话,可以开辟一个子线程,这个时候可用defaultRunLoopMode模式苹果推荐。

NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            
            //执行耗时间的代码
            
        }];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
        
        //开启当前的线程Runloop,否则timer调用不执行
        [[NSRunLoop currentRunLoop] run];
    }];
 //开启
 [thread start];

你可能感兴趣的:(RunLoop与Timer的使用)