源码

iOS 浅谈 Runloop

RunLoop 是什么

强烈推荐 ibireme 大神的文章深入理解RunLoop

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, nilNSStringFromClass([AppDelegate class]));
    }
}

这是因为程序自动帮我们在 UIApplicationMain… 中做了这个事情。

下面来看看 Runloop 的简化的伪代码,主要来自 sunnyxx  大神的一次视频分享:

function loop({
    do {
        有事干了 = 我睡觉了没事别找我();
        if (搬砖) {
            搬砖();
        } else if (吃饭) {
            吃饭();
        }
    } while (活着)
}

这个伪代码看着还是有一点抽象,需要了解的一个知识点是线程和 RunLoop 之间是一一对应的,这里的睡觉了可以理解为线程休眠 [NSThread sleepUntilDate:...]],也就是说当应用没有任何事件触发时,就会停在睡觉那行代码不执行,这样就节约了 CPU 的运算资源,提高程序性能,直到有事件唤醒应用为止。例如上面的搬砖事件,吃饭事件。处理完后,又会进入睡觉状态直到下次唤醒,反复循环,这样就保证了程序能随时处理各种事件并能够稳定运行。

实际上触摸事件、屏幕 UI 刷新、延迟回调等等都是 Runloop 实现的。

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;
    // ...
};

先不管这些东西是干什么的,至少我们现在能够得出如下图所示的理解:

(0)

本文由 投稿者 创作,文章地址:https://blog.isoyu.com/archives/ios-qiantan-runloop.html
采用知识共享署名4.0 国际许可协议进行许可。除注明转载/出处外,均为本站原创或翻译,转载前请务必署名。最后编辑时间为:1月 7, 2019 at 02:45 下午

热评文章

发表回复

[必填]

我是人?

提交后请等待三秒以免造成未提交成功和重复