强烈推荐 ibireme 大神的文章深入理解RunLoop
关于 Runloop ,尽管早就知道它的本质实现是一个循环,但笔者还是一直很困惑它的作用是什么 ,不过最近整理相关知识总算是理解了。
代码的执行逻辑是自上而下的,如果没有 Runloop ,代码执行完毕后,程序就退出了,对应到实际场景就是 APP 一打开立马就退出了。
int main(int argc, const char * argv[]) {
@autoreleasepool {
NSLog(@"程序执行中...");
}
return 0;
}
// log
程序执行中...
Program ended with exit code: 0
例如上面的代码,代码执行完毕后,main 函数返回,然后程序退出。
为什么工作中,好像没有编写 Runloop 相关的代码,程序还是能够稳定持续运行呢?
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
这是因为程序自动帮我们在 UIApplicationMain… 中做了这个事情。
下面来看看 Runloop 的简化的伪代码,主要来自 sunnyxx 大神的一次视频分享:
function loop() {
do {
有事干了 = 我睡觉了没事别找我();
if (搬砖) {
搬砖();
} else if (吃饭) {
吃饭();
}
} while (活着)
}
这个伪代码看着还是有一点抽象,需要了解的一个知识点是线程和 RunLoop 之间是一一对应的,这里的睡觉了可以理解为线程休眠 [NSThread sleepUntilDate:...]],也就是说当应用没有任何事件触发时,就会停在睡觉那行代码不执行,这样就节约了 CPU 的运算资源,提高程序性能,直到有事件唤醒应用为止。例如上面的搬砖事件,吃饭事件。处理完后,又会进入睡觉状态直到下次唤醒,反复循环,这样就保证了程序能随时处理各种事件并能够稳定运行。
实际上触摸事件、屏幕 UI 刷新、延迟回调等等都是 Runloop 实现的。
先来看看 Runloop 的结构源码:
struct __CFRunLoop {
pthread_t _pthread;
CFMutableSetRef _commonModes;
CFMutableSetRef _commonModeItems;
CFRunLoopModeRef _currentMode;
CFMutableSetRef _modes;
// ...
};
这里包含一个线程的成员变量 _pthread,可以看出 Runloop 确实和线程是息息相关的。还能看到 Runloop 拥有很多关于 Model 的成员变量,再来看看 Model 的结构:
struct __CFRunLoopMode {
CFStringRef _name;
CFMutableSetRef _sources0;
CFMutableSetRef _sources1;
CFMutableArrayRef _observers;
CFMutableArrayRef _timers;
// ...
};
先不管这些东西是干什么的,至少我们现在能够得出如下图所示的理解:
本文由 投稿者 创作,文章地址:https://blog.isoyu.com/archives/ios-qiantan-runloop.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:1月 7, 2019 at 02:45 下午