查看oc文件底層結(jié)構(gòu)
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc xxx.m
支持ARC、指定運行時系統(tǒng)版本
xcrun -sdk iphoneos clang -arch arm64 -rewrite-objc -fobjc-arc -fobjc-runtime=ios-15.0.0 xxx.m
一、RunLoop基礎(chǔ)
1. RunLoop對象
-
iOS中有兩套API來訪問和使用RunLoop-
Foundation:NSRunLoop -
Core Foundation:CFRunLoopRef
-
-
RunLoop和CFRunloopRef都代表著RunLoop對象-
NSRunloop是基于CFRunLoopRef的一層OC包裝 -
CFRunLoopRef是開源的
-
-
Foundation
-
[NSRunLoop currentRunLoop];獲得當(dāng)前線程的RunLoop對象 -
[NSRunLoop mainRunLoop];獲得主線程的RunLoop對象
-
-
Core Foundation
-
CFRunLoopRefGetCurrent();獲得當(dāng)前線程的RunLoop對象 -
CFRunLoopRefGetMain();獲得主線程的RunLoop對象
-
注:https://opensource.apple.com/tarballs/CF/
- 程序并不會馬上退出,而是保持運行狀態(tài)
-
RunLoop的基本作用- 保持程序的持續(xù)運行
- 處理App中各種事件(如:觸摸事件、定時器事件等)
- 節(jié)省CPU資源,提高程序性能:該做事時做事,該休息時休息
-
……
RunLoop的基本作用1.png
RunLoop的基本作用2.png
2 . RunLoop與線程
- 每條線程都有唯一的一個與之對應(yīng)的
RunLoop對象 -
RunLoop保存在一個全局的Dictionary里,線程作為key,RunLoop作為value - 線程剛創(chuàng)建時并沒有
RunLoop對象,RunLoop會在第一次獲取它時創(chuàng)建 -
RunLoop會在線程結(jié)束時銷毀 - 主線程的
RunLoop已經(jīng)自動獲?。▌?chuàng)建),子線程默認沒有開啟RunLoop
3. RunLoop相關(guān)的類
- Core Foundation中關(guān)于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相關(guān)的類.png
-
CFRunLoopModeRef
-
CFRunLoopModeRef代表RunLoop的運行模式 - 一個
RunLoop包含若干個Mode,每一個Mode又包含若干個sources0/sources1/Timer/observer -
RunLoop啟動時只能選擇其中一個Mode作為currentMode - 如果需要切換
Mode,只能退出當(dāng)前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的線程間通信
- 系統(tǒng)事件捕捉
- Timers
- NSTimer
performSelector:withObject:afterDelay:
- Observers
- 用于監(jiān)聽
RunLoop的狀態(tài) - UI刷新(
BeforeWaiting) -
Autorelease pool(BeforeWaiting)
- 用于監(jiān)聽

RunLoop的運行邏輯.png
三、RunLoop休眠的實現(xiàn)原理
- 等待消息
- 沒有消息就讓線程休眠
-
有消息就喚醒線程
RunLoop休眠的實現(xiàn)原理.png
四、RunLoop在實際的應(yīng)用
- 控制線程生命周期(線程?;睿?/li>
- 解決
NSTimer在滑動時停止工作的問題 - 監(jiān)控應(yīng)用卡頓
- 性能優(yōu)化
注:可能涉及的面試題
- 講講
RunLoop,項目中有用到嗎 -
RunLoop內(nèi)部實現(xiàn)邏輯 -
RunLoop和線程的關(guān)系 -
timer與RunLoop的關(guān)系 - 程序中添加每3秒響應(yīng)一次的
NSTimer,當(dāng)拖動tableView時timer可能無法響應(yīng)要怎么解決 -
RunLoop是怎么響應(yīng)用戶操作的,具體流程是什么樣的 - 說說
RunLoop的幾種狀態(tài) -
RunLoop的mode作用是什么
上一篇:
OC底層基礎(chǔ):Block
下一篇:
OC底層基礎(chǔ):多線程GCD


