NSTimer是基于runloop进行消息分派,调度NSTimer,其实是要求当前运行循环在某个特定的时间分配某个选择器
什么是runloop,网上有很多资料,我就不说了,技术浅薄,也说不太清楚只要记住一点就是:
每个应用程序都是一个处于阻塞的do/while循环驱动,当有事件发生时候,就把事件分派给合适的监听器,没有事件,就让线程处于休眠,如此反复直到循环停止,处理分派的对象就是 NSRunloop,每个线程都有自己的runloop,只是主线程默认是开启的,其他线程需要我们自己手动开启
创建NSTimer的几个方法:
第一个方法:
这个方法默认把定时器加到当前线程的runloop defaultMode中,如果在是在主线程中定时器自动启动(因为主线程runloop默认开启的),如果是子线程还要启动子线程的runloop定时器才能启动,所以我们平常创建定时器的时候就是用这种方法创建
第二个方法:
这个方法不会将定时器加到当前线程的runloop中,所以不会自动启动,需要你手动添加到runloop中,并且设置runloopMode,所以如果想设置自己的runloopmode 你就用这个方法,不用第一个
repeats:如果为YES,会不断重置时间根据间隔时间不断运行直到调用invalidated方法变成invalidated状态,才会停止。如果为NO,当触发fire方法后会自动变成invalidated状态,自动停止。
fireDate:属性表示触发定时器中selector的时间,[NSDate date]+interval后才触发selector,所以如果想让定时器立即触发,就设置[NSDate date] 当前时间
注意在主线程中,如果有耗时的操作,阻塞主线程的时候,NSTimer会暂停的,直到那个操作运行结束,然后NSTimer会继续运行,但是定时器会立马会把阻塞时间内没有触发的selector次数加速运行去弥补那个阶段的selector,然后在趋于稳定的间隔时间内触发selector
当scrollView在滚动的时候,主线程的runloop会自动切换成UITrackingRunLoopMode,NSTimer会中途停止,当滚动结束的又会恢复之前的kCFRunLoopDefaultMode,NSTimer又会启动。
如果设置当前runloop mode为CommonMode,NSTimer就可以在scrollView滚动的也不会中途停止
runloopmode是一个集合,包括监听:事件源,定时器,以及需通知的runloop observers
每次运行一个run loop,你指定(显式或隐式)run loop的运行模式。当相应的模式传递给run loop时,只有与该模式对应的input sources才被监控并允许run loop对事件进行处理(与此类似,也只有与该模式对应的observers才会被通知)
模式包括:
default模式:几乎包括所有输入源(除NSConnection) NSDefaultRunLoopMode模式
mode模式:处理modal panels
connection模式:处理NSConnection事件,属于系统内部,用户基本不用
event tracking模式:如组件拖动输入源 UITrackingRunLoopModes 不处理定时事件
common modes模式:NSRunLoopCommonModes 这是一组可配置的通用模式。将input sources与该模式关联则同时也将input sources与该组中的其它模式进行了关联。