面试复习-Runloop相关

什么是Runloop

运行循环,在程序运行中做事情

  • 定时器,performSelector
  • GCD Async queue
  • 事件响应,手势识别,页面刷新
  • 网络请求
  • autoreleasepool

卡顿检测 https://www.jianshu.com/p/d0aab0eb8ce4

新开线程,用 while YES 加一个信号量,在 回调(runloop循环会调用)中去打开信号量,计算次数
卡顿时runloop在做什么 activity == kCFRunLoopBeforeSources || activity == kCFRunLoopAfterWaiting
休眠时 before Waiting
1s 看任务情况大概几个几十个循环都有可能

runloop底层结构

结构体,内部有_pthread/commonModes/commonModelItems/_currentMode 和modes
其中 modes 里面装的是 各种模式。
每个模式里面有 name, source0,source1,obsevers,timer (都是set)

  • 一个runloop包含若干mode,每个mode包含若干 source0/source1/timer/Observer
  • 每次只能选择一个mode,切换mode需要退出当前loop,重新选择
  • 不同组的source0/source1/timer/observer互不干扰
  • mode没有事件会立即退出

runloop与线程

每条线程都有与之对应的runloop对象
runloop保存在全局的dictionary,key=线程,value=runloop
线程刚创建不会有runloop对象,第一次获取时创建
runloop在线程结束时销毁
主线程默认开启runloop,子线程默认没有开启

常见2种mode

default 默认
tracking scrollview

runloop运行逻辑

  1. 通知 observers 进入loop
  2. 通知 observers 即将处理timer
  3. observers 即将处理sources
  4. 处理 blocks
  5. 处理source0
  6. 如存在source1 ->8
  7. 通知 observers 开始休眠
  8. 通知 observers 结束休眠 (处理 timer,GCD Async To Main Queue,source1)
  9. 处理 Blocks
  10. 根据结果继续 runloop或者 退出
  11. 通知 observers 退出 loop

Source0:触摸事件,performSelector:onTnread:
Source1:port通信,系统事件捕捉

Source1 :基于mach_Port的,来自系统内核或者其他进程或线程的事件,可以主动唤醒休眠中的RunLoop(iOS里进程间通信开发过程中我们一般不主动使用)。mach_port大家就理解成进程间相互发送消息的一种机制就好, 比如屏幕点击, 网络数据的传输都会触发sourse1。
• Source0 :非基于Port的 处理事件,什么叫非基于Port的呢?就是说你这个消息不是其他进程或者内核直接发送给你的。一般是APP内部的事件, 比如hitTest:withEvent的处理, performSelectors的事件.

简单举个例子:一个APP在前台静止着,此时,用户用手指点击了一下APP界面,那么过程就是下面这样的:

我们触摸屏幕,先摸到硬件(屏幕),屏幕表面的事件会被IOKit先包装成Event,通过mach_Port传给正在活跃的APP , Event先告诉source1(mach_port),source1唤醒RunLoop, 然后将事件Event分发给source0,然后由source0来处理。
Timers:NSTimer,performSelector:withObject:afterDelay:
Observes: 监控runloop状态,UI刷新(before waiting),AutoreleasePool(before waiting)

runloop运用

  1. 线程保活
  2. 解决NSTimer滑动停止
  3. 监控卡顿,性能优化

你可能感兴趣的:(面试复习-Runloop相关)