定时器是开发中经常会接触的一个类型
苹果公司在Foundation框架中提供了一个非常好用的定时器类——NSTimer,几乎可以完成所有的定时操作
NSTimer 最常见的用法是,直接调用以下方法:
[NSTimer scheduledTimerWithTimeInterval:1
target:self
selector:@selector(timerAction:)
userInfo:nil
repeats:YES];
这个方法的几个参数,分别是:
time interval,定时器运行的时间间隔
target,是定时器作用的目标对象
selector,是方法选择器,选择定时调用的方法
user info,是传递到上述方法中的信息
repeats,是否重复执行
这个类方法的返回值是NSTimer,但是不接收该返回值,直接就可以启动定时器。
调用上述方法之后,直接就会创建一个定时器,然后这个定时器自动开始执行,每隔固定时间会调用定时器方法timerAction:
NSTimer另外一个类似的方法是
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
直接调用这个方法也会创建一个定时器,但是运行时,不会看到定时器的运行
NSTimer *timer = [NSTimer timerWithTimeInterval:1
target:self
selector:@selector(timerAction:)
userInfo:nil
repeats:YES];
需要自己手动开启定时器,调用如下方法
[timer fire];
但是定时器依然不会启动
因为OC中,定时器的启动,是依赖于当前线程的事件循环的,也即NSTimer的运行,需要依赖当前线程的run loop
所以上述定时器在启动前,需要添加到一个run loop中
如下:
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
这样再调用定时器的fire方法,就会启动定时器。
其实将定时器添加到当前run loop之后,定时器在设定的时间间隔之后就会自动启动,而fire方法,会立即触发定时器
官方文档中说:
在重复执行的定时器中调用此方法后立即触发该定时器,但不会中断其之前的执行计划;
在不重复执行的定时器中调用此方法,立即触发后,就会使这个定时器失效。
所以NSTimer的第一个方法,其实做了如下几件事情:
1. 创建一个NSTimer的定时器对象
2. 将这个定时器对象添加到当前线程的run loop上
3. 开启这个定时器
在iOS的开发中,UIApplication创建之后,会自动开启一个不断运行的run loop,保证应用程序不会退出,一直响应用户事件
所以添加的定时器会自动运行下去
而在一般的OC语言学习中,若想让程序不断运行,需要自己手动设置当前线程的runloop不断运行
[[NSRunLoop currentRunLoop] run];
如果想停止定时器,只需要调用定时器的invalidate方法,就可以终止定时器,同时将定时器从当前run loop中移除
[timer invalidate];
注意:
1. NSTimer可以精确到50-100毫秒
2. NSTimer并不是绝对精确的,因为它需要添加到当前线程上启动,如果线程受阻,那么定时器就租塞或者会跳过一段时间。