深入浅出 RunLoop(一):初识
深入浅出 RunLoop(二):数据结构
深入浅出 RunLoop(三):事件循环机制
深入浅出 RunLoop(四):RunLoop 与线程
深入浅出 RunLoop(五):RunLoop 与 NSTimer
深入浅出 RunLoop(六):相关面试题
前言
前面我们介绍了
RunLoop
的基本概念以及相关数据结构,这篇我们来讲解一下RunLoop
到底是怎么工作的。
首先我们来看一下主线程的RunLoop
的启动过程。
前面我们说过,我们的 iOS 程序能保持持续运行的原因就是在main()
函数中调用了UIApplicationMain
函数,这个函数内部会启动主线程的RunLoop
。
打断点,通过 LLDB 指令bt
查看函数调用栈如下:
UIApplicationMain
函数中调用了 Core Foundation 框架下的CFRunLoopRunSpecific
函数。
查看源码中该函数的实现,如下:
SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) { /* DOES CALLOUT */ CHECK_FOR_FORK(); if (__CFRunLoopIsDeallocating(rl)) return kCFRunLoopRunFinished; __CFRunLoopLock(rl); // 根据 modeName 找到本次运行的 mode CFRunLoopModeRef currentMode = __CFRunLoopFindMode(rl, modeName, false); // 如果没找到 || mode 中没有注册任何事件,则就此停止,不进入循环 if (NULL == currentMode || __CFRunLoopModeIsEmpty(rl, currentMode, rl->_currentMode)) { Boolean did = false; if (currentMode) __CFRunLoopModeUnlock(currentMode); __CFRunLoopUnlock(rl); return did ? kCFRunLoopRunHandledSource : kCFRunLoopRunFinished; } volatile _per_run_data *previousPerRun = __CFRunLoopPushPerRunData(rl); CFRunLoopModeRef previousMode = rl->_currentMode; rl->_currentMode = currentMode; int32_t result = kCFRunLoopRunFinished; // 通知 Observers:即将进入 RunLoop if (currentMode->_observerMask & kCFRunLoopEntry ) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry); // RunLoop 具体要做的事情 result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode); // 通知 Observers:即将退出 RunLoop if (currentMode->_observerMask & kCFRunLoopExit ) __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit); __CFRunLoopModeUnlock(currentMode); __CFRunLoopPopPerRunData(rl, previousPerRun); rl->_currentMode = previousMode; __CFRunLoopUnlock(rl); return result; } 复制代码
删掉不重要的细节:
SInt32 CFRunLoopRunSpecific(CFRunLoopRef rl, CFStringRef modeName, CFTimeInterval seconds, Boolean returnAfterSourceHandled) { /* DOES CALLOUT */ // 通知 Observers:即将进入 RunLoop __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopEntry); // RunLoop 具体要做的事情 result = __CFRunLoopRun(rl, currentMode, seconds, returnAfterSourceHandled, previousMode); // 通知 Observers:即将退出 RunLoop __CFRunLoopDoObservers(rl, currentMode, kCFRunLoopExit); return result; } 复制代码
从函数调用栈,以及CFRunLoopRunSpecific
函数的实现中可以得知,RunLoop
事件循环的实现机制体现在__CFRunLoopRun
函数中。