一、首先 我们先来认识一下 RunLoop
RunLoop: 就是运行循环(在程序运行过程中循环做一些事情)
应用范围:比如 定时器 GCD 事件响应 手势识别 界面刷新 网络请求等等。
先来看一个例子:
得到的结果是:程序执行完 14行 程序将会退出。
如果是下面这种写法 ,又会是怎么个情况啦。
此时 程序并不会马上退出,而是保持运行状态。
UIApplicationMain这个函数并不能看到源码 ,但是它能让程序保持当前状态 ,这其中就用到了RunLoop。
RunLoop基本作用:
1.保持程序的持续运行
2.处理APP中的各种事件(比如触摸、定时器等)
3.节约CPU资源、提高程序性能:该做事时做事,该休息时休息
4.......
二、在IOS中 有2套API来访问和使用RunLoop
- Foundation:NSRunLoop
- Core Foundation:CFRunLoopRef
三、RunLoop与线程的关系
1、每条线程都有唯一的一个与之对应的RunLoop对象
2、RunLoop保存在一个全局的Dictionary里,线程作为key,RunLoop作为value
3、线程刚创建时并没有RunLoop对象,RunLoop会在第一次获取它时创建
4、RunLoop会在线程结束时销毁
5、主线程的RunLoop已经自动获取,子线程默认没有开启RunLoop
四、RunLoop相关的类
其中 CFRunLoopModeRef又是如下结构
CFRunLoopModeRef代表RunLoop的运行模式
一个RunLoop包含了若干个Mode,每个Mode又包含若干个Source0/Source1/Timer/Observer
RunLoop启动时只能选择其中一个Mode,做为当前Mode
如果需要切换Mode,只能退出当前Loop,再重新选择一个Mode进入,不同组的Source0/Source1/Timer/Observer能分割开来,互不影响
如果Mode里面没有任何Source0/Source1/Timer/Observer,RunLoop会立马退出
如图:
我们最常使用的有2种Mode
- kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默认Mode,通常主线程是在这个Mode下运行
- UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
五、RunLoop的状态
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), // 即将进入Loop
kCFRunLoopBeforeTimers = (1UL << 1), // 即将处理Timer
kCFRunLoopBeforeSources = (1UL << 2), // 即将处理Sources
kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
kCFRunLoopAfterWaiting = (1UL << 6), // 刚从休眠中唤醒
kCFRunLoopExit = (1UL << 7), // 即将退出Loop
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
五、RunLoop运行逻辑
五、RunLoop休眠的实现原理
RunLoop如果即将进入休眠状态 会从用户态(mach_msg())切换到 内核态(mach_msg()) ----没有消息就让线程休息
有消息就会唤醒线程 重新进入用户态处理消息
注:如有错误,欢迎大家指正!知识点仅供学习使用!