查看oc文件底层结构
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc xxx.m
支持ARC、指定运行时系统版本
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-15.0.0 xxx.m
一、RunLoop基础
1. RunLoop对象
-
iOS中有两套API来访问和使用RunLoop-
Foundation:NSRunLoop -
Core Foundation:CFRunLoopRef
-
-
RunLoop和CFRunloopRef都代表着RunLoop对象-
NSRunloop是基于CFRunLoopRef的一层OC包装 -
CFRunLoopRef是开源的
-
-
Foundation
-
[NSRunLoop currentRunLoop];获得当前线程的RunLoop对象 -
[NSRunLoop mainRunLoop];获得主线程的RunLoop对象
-
-
Core Foundation
-
CFRunLoopRefGetCurrent();获得当前线程的RunLoop对象 -
CFRunLoopRefGetMain();获得主线程的RunLoop对象
-
注:https://opensource.apple.com/tarballs/CF/
- 程序并不会马上退出,而是保持运行状态
-
RunLoop的基本作用- 保持程序的持续运行
- 处理App中各种事件(如:触摸事件、定时器事件等)
- 节省CPU资源,提高程序性能:该做事时做事,该休息时休息
-
……
RunLoop的基本作用1.png
RunLoop的基本作用2.png
2 . RunLoop与线程
- 每条线程都有唯一的一个与之对应的
RunLoop对象 -
RunLoop保存在一个全局的Dictionary里,线程作为key,RunLoop作为value - 线程刚创建时并没有
RunLoop对象,RunLoop会在第一次获取它时创建 -
RunLoop会在线程结束时销毁 - 主线程的
RunLoop已经自动获取(创建),子线程默认没有开启RunLoop
3. RunLoop相关的类
- Core Foundation中关于RunLoop的5个类
CFRunLoopRefCFRunLoopModeRefCFRunLoopSourceRefCFRunLoopTimerRefCFRunLoopObserverRef
typedef struct __CFRunLoop * CFRunLoopRef;
struct __CFRunLoop {
pthread_t _pthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
};
typedef struct __CFRunLoopMode *CFRunLoopModeRef;
struct __CFRunLoopMode {
CFStringRef _name;
CFMutableSetRef _sources0;
CFMutableSetRef _sources1;
CFMutableArrayRef _observers;
CFMutableArrayRef _timers;
};

RunLoop相关的类.png
-
CFRunLoopModeRef
-
CFRunLoopModeRef代表RunLoop的运行模式 - 一个
RunLoop包含若干个Mode,每一个Mode又包含若干个sources0/sources1/Timer/observer -
RunLoop启动时只能选择其中一个Mode作为currentMode - 如果需要切换
Mode,只能退出当前Loop,再重新选择一个Mode进入- 不同组的
sources0/sources1/Timer/observer能分隔开来,互不影响
- 不同组的
- 如果
Mode里没有sources0/sources1/Timer/observer,RunLoop会立马退出 - 常见的两种Mode
-
kCFRunLoopDefaultMode(NSDefaultRunLoopMode):App的默认Mode,通常主线程是在这个Mode下运行 -
UITrackingRunLoopMode:界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode影响
-
-
CFRunLoopObserverRef
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0), //即将进入Loop
kCFRunLoopBeforeTimers = (1UL << 1), // 即将处理Timer
kCFRunLoopBeforeSources = (1UL << 2), // 即将处理Source
kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
kCFRunLoopAfterWaiting = (1UL << 6), // 刚从休眠中唤醒
kCFRunLoopExit = (1UL << 7), // 即将退出Loop
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
二、RunLoop的运行逻辑
- Source0
- 触摸事件处理
performSelector:onThread:
- Source1
- 基于Port的线程间通信
- 系统事件捕捉
- Timers
- NSTimer
performSelector:withObject:afterDelay:
- Observers
- 用于监听
RunLoop的状态 - UI刷新(
BeforeWaiting) -
Autorelease pool(BeforeWaiting)
- 用于监听

RunLoop的运行逻辑.png
三、RunLoop休眠的实现原理
- 等待消息
- 没有消息就让线程休眠
-
有消息就唤醒线程
RunLoop休眠的实现原理.png
四、RunLoop在实际的应用
- 控制线程生命周期(线程保活)
- 解决
NSTimer在滑动时停止工作的问题 - 监控应用卡顿
- 性能优化
注:可能涉及的面试题
- 讲讲
RunLoop,项目中有用到吗 -
RunLoop内部实现逻辑 -
RunLoop和线程的关系 -
timer与RunLoop的关系 - 程序中添加每3秒响应一次的
NSTimer,当拖动tableView时timer可能无法响应要怎么解决 -
RunLoop是怎么响应用户操作的,具体流程是什么样的 - 说说
RunLoop的几种状态 -
RunLoop的mode作用是什么
上一篇:
OC底层基础:Block
下一篇:
OC底层基础:多线程GCD


