RunLoop的主要数据结构
- CFRunLoopObserver
观测时间点
kCFRunLoopEntry
kCFRunLoopBeforeTimers
kCFRunLoopBeforeSources
kCFRunLoopBeforeWaiting
kCFRunLoopAfterWaiting
kCFRunLoopExit
- 一个RunLoop可以有多个mode,一个mode可以有多个sources,observers,times
1.什么是RunLoop?
RunLoop是通过内部维护的
事件循环
来对事件/消息进行管理
的一个对象。
事件循环:
没有消息需要处理时,休眠以避免资源占用
有消息需要处理时,立刻被唤醒
2.RunLoop可以做什么。
1.可以处理Crash (程序出现异常,捕获之后,强制程序runloop)
2.保持线程存活。
3.检测,分析,优化卡顿问题。
3.什么是事件循环?
内部维护的事件循环可以用来不断的处理消息/事件,对他们进行管理,同时当没有消息需要处理时,会从用户态到内核态的切换。由此可以用来进行当前线程的休眠,然后避免资源占用。
同时当有消息进行处理时,会从内核态到用户态的切换。然后当前的用户线程会被唤醒。
4.main函数为什么会保持运行状态不退出?
main函数会调用UIApplicationMain函数,而在函数内部实际上会启动主线程的RunLoop,而RunLoop特点就是没有消息需要处理时,会从用户态到内核态的切换,进行休眠。当有消息进行处理时,会从内核态到用户态的切换。然后当前的用户线程会被唤醒。
5.滑动TableView的时候,我们的定时器还会生效吗?
不会,正常情况会运行在kCFRunLoopDefaultMode模式,当滑动TableView的时候,会从kCFRunLoopDefaultMode切换到UITrackingRunLoopMode。当我们将Timer添加到一个mode上之后,如果切换到另外一个模式上,就不会响应了。如果有多个mode的话,可以添加到NSRunLoopCommonModes上。
6.RunLoop与线程是怎样的关系?
线程与RunLoop是一一对应的关系。并且是以key和value健值对进行存储的。
一个线程默认是没有RunLoop的,我们需要为它手动创建。
7.如何实现一个常驻线程?
1.为当前线程开启一个RunLoop。
2.向该RunLoop当中添加一个Sources或者timer等维持RunLoop的事件循环。
3.调用该RunLoop。
8.怎样保证子线程数据回来更新UI的时候不打断用户的滑动操作?
滑动的时候,会运行在UITrackingRunLoopMode模式下。一般网络请求会在子线程中,更新数据更新UI的时候,可以包装起来提交到主线程的kCFRunLoopDefaultMode模式下。因为mode不一样,所以不会打断。
9.主线程没有事件源(sources或者timer),子线程需要事件源(sources或者timer)才可以运行。
在网上看到一篇对RunLoop讲述挺好的文章,在此记录一下。
深入理解RunLoop