1、什么是RunLoop?
2、main函数为什么一直不退出呢?
3、RunLoop是怎么维护的循环?
什么是RunLoop?
RunLoop是通过内部维护的一个事件循环来对事件/消息进行管理的一个对象。
目的是:
- 没有消息处理时,休眠以避免资源占用。同时会对线程由用户态切换到内核态。
- 当有消息进行处理时,立即被唤醒。 会对线程通内核态到用户态的切换,同时线程会被唤醒。
main函数为什么能保持不退出呢?
因为在main函数启动后,在内部会调用UIApplicationMain函数,在这个函数内部实际上会启动主线程的一个运行循环即RunLoop,RunLoop可以接受一些事件/消息,并对这些事件/消息进行处理,处理完之后再继续进行等待,这里循环不单单的是一个while循环,而是用户态和内核态之间的相互切换。
RunLoop是怎么维护的循环?
RunLoop是CFRunLoop的封装,提供面向对象的API。
在RunLoop中有五大类
- CFRunLoop
- CFRunLoopMode
- Source/Timer/Observer
其中
- source0 事件 需要手动唤醒线程
- source1 事件 具备唤醒线程的能力
CFRunLoopObserver
检测时间点:
- kCFRunLoopEntry
- kCFRunLoopTimes
- kCFRunLoopObservers
- kCFRunLoopBeforeWaiting
- kCFRunLoopAfterWaiting
- kCFRunLoopExit
RunLoop与线程时一一对应的关系,RunLoop与mode是一对多,mode和Source/Timer/Observer是一对多
CFRunLoopMode.png
commonMode特殊性:
- commonMode
不是实际存在
的一种mode - 是同步Source/Timer/Observer到多个Mode的一种方案。
事件循环的实现机制
点击App图标,系统是如何进行启动,休眠和退出的?
- 系统启动后,会先执行main函数
- 在main函数内部会调用UIApplicationMain函数,启动主线程的RunLoop
- 通知Observe将要处理Timer/Source0事件
- 处理source0事件
- 如果有source1事件要处理,那么处理唤醒时收到的消息
- 如果没有事件要处理了,通知observe线程进入休眠,等待唤醒
- 当线程RunLoop接受到Source1,Timer事件或者外部手动唤醒,这时通过Mach-Port线程会被唤醒,从内核态进入到用户态,处理事件
- 当线程退出时,会通知observe退出RunLoop
RunLoop核心
网友评论