Runloop 的五种mode

1.runloop是一个事件驱动的循环,收到事件就去处理,没有事件就进入睡眠.
2.应用一启动主线程被创建后,主线程对应的runloop也被创建,runloop也保证了程序能够一直运行.之后创建的子线程默认是没有runloop的,只有当调用[NSRunLoop currentRunLoop]去获取的时候才被创建.
3.runloop的模式:
mode一共五种:

  • NSDefaultRunLoopMode 默认
  • UITrackingRunLoopMode UI专用
  • UIInitializationRunLoopMode 在刚启动App时第进入的第一个Mode,启动完成后就不再使用
  • GSEventReceiveRunLoopMode 接受系统事件的内部Mode
  • NSRunLoopCommonModes 这是一个占位用的Mode,不是一种真正的Mode

场景: 当一个页面中添加了UIScrollView  同时还有一个定时器的时候,当UIScrollView 滑动的时候, 定时器是不工作的,

原因:

我们将timer添加到当前的主线程中,并且选择NSDefaultRunLoopMode这个默认的模式。默认是正常执行的,当滑动UIScrollView的时候,UI发生了交互,此时主线程Runloop就会转到UITrackingRunLoopMode下 ,timer就停下来了.
模式类似于跑道,一个runloop同时只能在一个跑道上进行,并且模式有优先级, UITrackingRunLoopMode是UI模式,是优先级最高的模式,当runloop遇到事件的时候,会根据事件指定的模式,去切换跑到,UITrackingRunLoopMode的优先级最高,所以就切换到了这个模式上,这时候其他模式下的事件就不会被执行.
并且UITrackingRunLoopMode只能被UI事件唤醒,如果将上面的timer指定的模式改成UI模式,那么默认是不会执行的,但是当滑动textView时,跑到就切换到了UI模式,timer就可以执行了,一旦停止滑动,timer又会停 下来.
NSRunLoopCommonModes实质就是NSDefaultRunLoopMode和UITrackingRunLoopMode,等同于在两个模式上都添加一遍,不管是那个跑道,都会遇到timer的事件.


所以定义NSTimer 的时候,最好直接添加到NSRunLoopCommonModes 下,

timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timeEvent) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer: timer forMode:NSRunLoopCommonModes];

你可能感兴趣的:(ios)