Runloop
Runloop是通内部维护的事件循环来对事件、消息进行管理的一个对象,线程和runloop是一一对应的关系
没有消息需要处理时,休眠以避免资源占用(用户态-》内核态)
有消息需要处理时,会立刻被唤醒(内核态-》用户态)
UIApplicationMain开启了runloop,所以程序保持一直运行
等待不等于死循环
NSRunLoop是对CFRunLoop的封装提供了面向对象的API其结构有
CFRunLoop(pthread、currentMode、modes、commonModes、commonMedeItems)
CFRunLoopMode(name(如NSDefaultRunLoopMode)、sources0,sources1、observers、timers)
Source/Timer/Observer
CFRunLoopSource
source0,需要手动唤醒线程
source1,具备唤醒线程的能力
CFRunLoopTimer是基于事件的定时器可以和NSTimer进行桥转换的(toll-free bridged)
CFRunLoopObserver
观测事件点kCFRunLoopEnter、kCFRunLoopBeforeTimers,kCFRunLoopBeforeSources,kCFRunLoopBeforeWaiting,kCFRunLoopAfterWaiting,kCFRunloopExit
一个RunLoop是有多个Model,一个mode有sources,timers、observers
NSRunLoopCommonModes,并不是一种实际存在的Mode,是同步Source、timer、observer到多个mode当中的一种解决方案,并不是和kCFRunLoopDefaultMode一样
WX20191105-083054@2x.png创建的NSTimer是创建在kCFRunLoopDefaultMode,如果滑动屏幕RunLoop会切换到UITrackingRunLoopMode,所以不会计时器响应不了,将timer添加到当前runloop的commonMode中,实际上是添加到了多个RunLoop模式下
线程的RunLoop默认没有runloop的,为了实现常驻线程,需要为当前线程开启一个RunLoop,向当前runloop添加port或者source来维持runloop的事件循环,启动runloop
如何保证子线程回来的数据更新UI不打断用户的滑动操作,我们可以把任务提交到主线程的kCFRunLoopDefaultMode模式下,当用户停止滑动从UITrackingRunLoopMode模式切换到kCFRunLoopDefaultMode的时候才刷新UI