11.runloop相关面试题

run loop,指的是一直在运行中的循环。所以runloop需要和线程紧密的结合起来,没有线程,就没有人处理runloop中的事件,故而没有线程,runloop就没有存在的意义。

二者关系

  • 主线程的run loop是启动着的(默认),iOS的应用程序启动后,会有一个main()函数
int main(int argc, char * argv[]) {
   @autoreleasepool {
       return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
   }
}

其中UIApplicationMain()函数,会在主Thread中设置一个RunLoop对象,正是因为一直有一个NSRunLoop一直在运行着,所以程序可以在无操作时候休眠,有响应时立马工作。

  • 除了主线程外,对其它线程来说,run loop默认是没有启动的,如果你需要更多的线程交互则可以手动配置和启动,如果线程只是去执行一个长时间的已确定的任务则不需要。
  • 通过 [NSRunLoop currentRunLoop]来获取当前的runloop。

runloop中的mode的有哪些?都有什么作用

  • model 主要是用来指定事件在运行循环中的优先级的,分为:
  1. NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
  2. UITrackingRunLoopMode:ScrollView滑动时
  3. UIInitializationRunLoopMode:启动时
  4. NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集合
  • 苹果公开提供的 Mode 有两个:
  1. NSDefaultRunLoopMode(kCFRunLoopDefaultMode)
  2. NSRunLoopCommonModes(kCFRunLoopCommonModes)

拓展面试题

  • 以+ scheduledTimerWithTimeInterval...的方式触发的timer,在滑动页面上的列表时,timer会暂定回调,为什么?如何解决?
    RunLoop只能运行在一种mode下,如果要换mode,当前的loop也需要停下重启成新的。利用这个机制,ScrollView滚动过程中NSDefaultRunLoopMode(kCFRunLoopDefaultMode)的mode会切换到UITrackingRunLoopMode来保证ScrollView的流畅滑动:只能在NSDefaultRunLoopMode模式下处理的事件会影响ScrollView的滑动。

如果我们把一个NSTimer对象以NSDefaultRunLoopMode(kCFRunLoopDefaultMode)添加到主运行循环中的时候, ScrollView滚动过程中会因为mode的切换,而导致NSTimer将不再被调度。

同时因为mode还是可定制的,所以:

Timer计时会被scrollView的滑动影响的问题可以通过将timer添加到NSRunLoopCommonModes(kCFRunLoopCommonModes)来解决。代码如下:

//将timer添加到NSDefaultRunLoopMode中
[NSTimer scheduledTimerWithTimeInterval:1.0
     target:self
     selector:@selector(timerTick:)
     userInfo:nil
     repeats:YES];
//然后再添加到NSRunLoopCommonModes里
NSTimer *timer = [NSTimer timerWithTimeInterval:1.0
     target:self
     selector:@selector(timerTick:)
     userInfo:nil
     repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

你可能感兴趣的:(11.runloop相关面试题)