文章目录
- iOS - Runloop介绍
- 1. 简介
- 1.1 顾名思义
- 1.2. 应用范畴
- 1.3. 如果没有runloop
- 1.4. 如果有了runloop
- 2. Runloop对象
- 3. Runloop与线程
- 4. 获取Runloop对象
- 4.1 Foundation
- 4.2 Core Foundation
- 4.3 示例
- 5. Runloop相关的类
- 5.1 Core Foundation中关于RunLoop的5个类
- 5.2 CFRunLoopRef
- 5.3 CFRunLoopModeRef
- 5.4 相关的类之间的关系
- 5.4.1 CFRunLoopModeRef
- 5.4.1.1常见的2种Mode
- 5.5 Runloop状态
- 5.5.1 监听Runloop状态
iOS - Runloop介绍
1. 简介
1.1 顾名思义
- 运行循环
- 在程序运行过程中循环做一些事情
1.2. 应用范畴
- 定时器(Timer)、PerformSelector
- GCD Async Main Queue
- 事件响应、手势识别、界面刷新
- 网络请求
- AutoreleasePool
1.3. 如果没有runloop
执行完第13行代码后,会即将退出程序
1.4. 如果有了runloop
- 程序并不会马上退出,而是保持运行状态
- RunLoop的基本作用
- 保持程序的持续运行
- 处理App中的各种事件(比如触摸事件、定时器事件等)
- 节省CPU资源,提高程序性能:该做事时做事,该休息时休息
…
2. Runloop对象
-
iOS中有2套API来访问和使用RunLoop
-
Foundation:
NSRunLoop
-
Core Foundation:
CFRunLoopRef
-
-
NSRunLoop
和CFRunLoopRef
都代表着RunLoop对象- NSRunLoop是基于CFRunLoopRef的一层
OC包装
- CFRunLoopRef是
开源的
- NSRunLoop是基于CFRunLoopRef的一层
https://opensource.apple.com/tarballs/CF/
3. Runloop与线程
-
每条线程都有
唯一
的一个与之对应的RunLoop对象
-
RunLoop保存在一个
全局的Dictionary
里,线程
作为key
,RunLoop
作为value
-
线程
刚创建
时并没有
RunLoop对象,RunLoop会在第一次
获取它时创建
-
RunLoop会在
线程结束
时销毁
-
主线程
的RunLoop已经自动获取(创建),子线
程默认没有开启RunLoop
4. 获取Runloop对象
4.1 Foundation
- [NSRunLoop currentRunLoop];
// 获得当前线程的RunLoop对象
- [NSRunLoop mainRunLoop];
// 获得主线程的RunLoop对象
4.2 Core Foundation
CFRunLoopGetCurrent();
// 获得当前线程的RunLoop对象`- CFRunLoopGetMain();
// 获得主线程的RunLoop对象
4.3 示例
5. Runloop相关的类
5.1 Core Foundation中关于RunLoop的5个类
- CFRunLoopRef
- CFRunLoopModeRef
- CFRunLoopSourceRef
- CFRunLoopTimerRef
- CFRunLoopObserverRef
5.2 CFRunLoopRef
_modes
里面装了多个CFRunLoopModeRef
对象,其中只有一个mode作为_currentMode
5.3 CFRunLoopModeRef
5.4 相关的类之间的关系
CFRunLoopRef
里面装了多个CFRunLoopModeRef
对象CFRunLoopModeRef
对象里面装的是CFRunLoopSourceRef
、CFRunLoopTimerRef
、CFRunLoopObserverRef
5.4.1 CFRunLoopModeRef
-
CFRunLoopModeRef代表RunLoop的
运行模式
-
一个RunLoop包含
若干个Mode
,每个Mode又包含若干个Source0/Source1/Timer/Observer -
RunLoop启动时
只能
选择其中一个Mode
,作为currentMode
-
如果需要
切换Mode
,只能退出
当前Loop,再重新
选择一个Mode
进入- 不同组的
Source0
/Source1
/Timer
/Observer
能分隔开来,互不影响
- 不同组的
-
如果Mode里
没有
任何Source0
/Source1
/Timer
/Observer
,RunLoop会立马退出
5.4.1.1常见的2种Mode
-
kCFRunLoopDefaultMode
(NSDefaultRunLoopMode):App的默认Mode,通常主线程是在这个Mode下运行 -
UITrackingRunLoopMode
:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
5.5 Runloop状态
5.5.1 监听Runloop状态
CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(kCFAllocatorDefault, kCFRunLoopAllActivities, YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
switch (activity) {
case kCFRunLoopEntry: {
NSLog(@"kCFRunLoopEntry");
}
break;
case kCFRunLoopBeforeTimers: {
NSLog(@"kCFRunLoopBeforeTimers");
}
break;
case kCFRunLoopBeforeSources: {
NSLog(@"kCFRunLoopBeforeSources");
}
break;
case kCFRunLoopBeforeWaiting: {
NSLog(@"kCFRunLoopBeforeWaiting");
}
break;
case kCFRunLoopAfterWaiting: {
NSLog(@"kCFRunLoopAfterWaiting");
}
break;
case kCFRunLoopExit: {
NSLog(@"kCFRunLoopExit");
}
break;;
default:
break;
}
});
CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopCommonModes);
CFRelease(observer);
触发一次点击事件:
@oubijiexi