首 页 行业热点 新车 试驾评测 养车用车 车型库
当前位置:首页iOS timer计时器

iOS timer计时器

来源:好土汽车网
导读 iOS timer计时器

timer,计时器,就是用来计时的,可以将它和要处理的动作绑定起来,让这个动作在某段时间之后执行,或者周期性地执行。

一、timer的工作原理

timer的工作和run loop密不可分,由于平常我们使用Application Kit和UIKit来新建的app,在app的主线程启动的时候就自动启动了一个runloop,因此在主线程中使用timer感觉不到runloop的存在。如果要在分线程中使用timer,就必须要了解timer和runloop的协同工作原理,自己去新建runloop,让它和timer一起配合工作。
简短概括runloop和timer的工作关系就是,timer只负责计时,timer所绑定的动作,是由runloop来执行的。下面就来详细地讲讲这种关系。
我们知道,runloop运行的时候需要指定运行模式(run loop mode),runloop的运行模式规定了它要监听的事件源,以及事件发生时它要通知的对象。因此可以给runloop定义多种运行模式,runloop运行时,可以同时启用多个运行模式。
一个timer同一时间只可以注册到一个runloop中,但是可以添加到这个runloop的多个运行模式中。(下图表示了这个关系)

二、timer的具体使用

1、创建timer

(1)使用当前的runloop来创建一个timer

方法:

+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

参数TimeInterval是timer计时的周期长度,每隔时长TimeInterval,计时器就会清零一次。
这两个方法,完成一系列动作:

  • 创建timer;
  • 将它加入到当前runloop的默认运行模式中;
  • 让timer开始计时。

对于这种方式添加的timer,runloop就会等它的计时时长第一次达到TimeInterval时,才会执行它绑定的动作。

(2)自己新建一个timer,之后将它注册到某个runloop中

方法:

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

这两个方法可以返回一个timer。

之后要用runloop对象的方法将timer注册到这个runloop对象的某个运行模式中:

-(void)addTimer:(nonnull NSTimer *) forMode:(nonnull NSString *);

这样添加到runloop的timer会立即开始计时。

(3)初始化一个timer,并指明它绑定的动作被执行的时间点

方法:

- (instanceType)initWithFireDate:(nonnull NSDate *) interval:(NSTimeInterval) target:(nonnull id) selector:(nonnull SEL) userInfo:(nullable id) repeats:(BOOL)

这里的fireDate是个时间点,是相对于系统时间的,只要到达了这个时间点,runloop就会去执行timer绑定的动作。所以如果timer是一次性的,都不需要计时,interval这个参数就没有作用了。如果是重复的timer,才需要计时,参数interval才有用。

可以用setFireDate方法来给timer设定动作的执行时间。

2、停止timer

timer需要在runloop的管理下才会有效,停止timer,只要把它从它所在的runloop中清理掉就可以实现。(或者让runloop停止运行)。

(1)对于一次性的timer

一次性的timer都不用考虑这个问题,因为runloop执行完timer绑定的动作就会自动把这个timer从它所在的运行模式中清理掉。

(2)对于周期性的timer

方法:

-(void)invalidate;

对于周期性的timer才需要考虑这个问题。

要停止一个周期性的timer,要获取这个timer对象的引用,在需要清理timer的时候,主动调用该timer对象的invalidate方法即可。

当然,也可以对一次性的timer执行这个方法,在timer的动作被runloop执行之前调用invalidate方法,timer的动作就永远不会被执行了。

因篇幅问题不能全部显示,请点此查看更多更全内容