iOS中的Runloop

本节主要理解:
1.runloop的理解与介绍(相关类与mode)
2.runloop在开发中的应用(主动使用/隐性调用)
3.runloop与线程的关系
4.Runloop与NSTimer的关系

■应用范畴
口 定时器( Timer )、PerformSelector
口 GCD Async Main Queue
口 事件响应、手势识别、界面刷新
口 网络请求
口 AutoreleasePool
伪代码

int main (int argc ,char * argv[]) [
    @autoreleasepool {
          int retVal = 0;
          do {
            //睡眠中等待消息
            int message = sleep_ and_ _wait();
            //处理消息
            retVal = process. _message (message) ;
          } while (0 == retVal);
          return 0;
     }
}
一.runloop相关的类

Core Foundation关于RunLoop5↑类

  • CFRunLoopRef
  • CFRunLoopModeRef
  • CFRunLoopSourceRef
  • CFRunLoopTimerRef
  • CFRunLoopObserverRef

他们之间的关系可以用下图表示


图片.png

■Source0
触摸事件处理(事件响应)
口performSe lector: onThread :
Source0 只包含了一个回调(函数指针),它并不能主动触发事件。使用时,你需要先调用 CFRunLoopSourceSignal(source),将这个 Source 标记为待处理,然后手动调用 CFRunLoopWakeUp(runloop) 来唤醒 RunLoop,让其处理这个事件。

■Source1
口基于Port的线程间通信
口系统事件捕捉
Source1 包含了一个 mach_port 和一个回调(函数指针),被用于通过内核和其他线程相互发送消息。这种 Source 能主动唤醒 RunLoop 的线程。

■Timers
口NSTimer
口perform Selector:with0bject :afterDelay:

■Observers
口用于监听RunLoop的状态
口UI刷新( BeforeWaiting )
口 Autorelease pool ( BeforeWaiting )

二.RunloopMode

常见的2种Моdе
kCFRunLoopDefaultMode ( NSDefaultRunLoopMode ) : App的默认mode,通常主线程是在这个mode下运行
UITrackingRunLoopMode :界面跟踪mode,用于scrollview追踪触摸滚动,保证界面滑动时不受其他mode影响

当使用kCFRunLoopCommonModes模式监听runloop时,以上两种模式都将被监听到

二.Runloop在实际开发中的应用

1.控制线程的生命周期(线程保活)-如AFNetworking
往runloop中添加Source/Timer/Observer
run方法时无法停止的,它专门用来开启一个永不销毁的线程

[NSRunloop currentrunloop] run];

2.解决NSTimer在滑动时停止工作的问题
NSTimer是由RunLoop来管理的,NSTimer其实就是CFRunLoopTimerRef。
因为runloop只能运行在一种模式下,滚动时,会模式切换。
使用NSRunLoopCommonModes,会让NSTimer在两种模式下工作

    NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"%d", ++count);
    }];
//    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
//    [[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
    
    // NSDefaultRunLoopMode、UITrackingRunLoopMode才是真正存在的模式
    // NSRunLoopCommonModes并不是一个真的模式,它只是一个标记
    // timer能在_commonModes数组中存放的模式下工作
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

3.监控应用卡顿/性能优化
可以添加Observer到主线程RunLoop中,通过监听RunLoop状态切换的耗时,以达到监控卡顿的目的

面试题
1.讲讲RunLoop, ,项目中有用到吗?
-控制线程的生命周期/调度,(线程保活/线程间通讯切换)
解决NSTimer在滚动时停止工作的问题
监控应用卡顿
性能优化
2.runloop内部实现逻辑 ?
实际上 RunLoop 就是这样一个函数,其内部是一个 do-while 循环。当你调用 CFRunLoopRun() 时,线程就会一直停留在这个循环里;直到超时或被手动停止,该函数才会返回。

3.runloop和线程的关系 ?
一个线程对应一个runloop
线程在执行完任务后,会处于休眠状态,随时等待接受新的任务,而不是退出

只有主线程的RunLoop是默认开启的,所以程序在开启后,会一直运行,不会退出。其他线程的RunLoop如果需要开启,就手动开启

4.NSTimer 与runloop的关系?
1.NSTimer是由RunLoop来管理的,NSTimer其实就是CFRunLoopTimerRef。
2.子线程中创建Timer要将其Runloop开启[[NSRunLoop currentRunLoop]run];否则会不执行Timer事件

5.程序中添加每3秒响应一 次的NSTimer ,当拖动tableview时timer可能无法响应要怎么解决?
NSTimer是由RunLoop来管理的,NSTimer其实就是CFRunLoopTimerRef。
因为runloop只能运行在一种模式下,滚动时,会模式切换。
使用NSRunLoopCommonModes,会让NSTimer在两种模式下工作

6.runloop 是怎么响应用户操作的,具体流程是什么样的?

图片.png

(简介版:由source1接收事件,由source0响应触摸事件)
用户交互事件首先在 IOHID 层生成 HIDEvent,然后向事件处理线程的 Source1 的 mach port 发送 HIDEvent 消息,Source1 的回调函数将事件转化为 UIEvent 并筛选需要处理的事件推入待处理事件队列,向主线程的事件处理 Source0 发送信号,并唤醒主线程,主线程检查到事件处理 Source0 有待处理信号后,触发 Source0 的回调函数,从待处理事件队列中提取 UIEvent,最后进入 hit-test 等 UIEvent 事件响应流程。

7.说说runLoop的几种状态

图片.png

8.runloop的mode作用是什么 ?
model 主要是用来指定事件在运行循环中的优先级的,分为:

  • NSDefaultRunLoopMode(kCFRunLoopDefaultMode):默认,空闲状态
  • UITrackingRunLoopMode :ScrollView滑动时
  • UIInitializationRunLoopMode :启动时
  • NSRunLoopCommonModes(kCFRunLoopCommonModes):Mode集

参考
runloop详解

你可能感兴趣的:(iOS中的Runloop)