Run Loop引入
首先由一个问题引入,每一个iOS应用,它的入口是哪里?
毫无疑问,iOS应用是源于C语言,所以同C项目一样,它的入口是main函数,既然同C语言一样,为什么我们在新建的C工程中写一段printf("hello world"),当程序输出完后,马上就会退出,而iOS的main函数却可以做到一直不退出?iOS的main函数做了什么操作?答案就是因为有run loop的存在。 每当我们创建项目的时候,它的默认mian函数实现都是如下这个样子
int main(int argc, char * argv[]) {
@autoreleasepool {
return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
}
}
可以看到Apple并没有做太多事情,只加了一个autoreleasepool自动释放池,同时添加了一个函数,UIApplicationMain。这个函数由做了哪些事情?查看它的文档说明
这个函数用于初始化application对象(默认是UIApplication类对象)和application的代理对象(默认是AppDelegate)。 同时,它会创建并开启主运行循环,也就是主run loop,并开始处理事件。同时,如果在info.plist文件中通过NSMAinNibFile指定了main nib,这个函数也会加载nib文件。尽管这个函数声明了return type,但它从不会返回的,因为它是一个死循环,iOS的应用之所以能持续不断运行,就是因为它的存在,确切的说,是因为它开启了run loop。
run loop简介
run loop有两种语义。广义上它指的是Apple应用上的一种消息循环机制,一种让程序不停运行,并接收事件做出相应处理的机制。其他平台也有类似的处理机制,例如windows平台上的Event loop机制。它的核心就是如下一个死循环,当然这是伪代码,意在简单描述下run loop所做操作:
int loop(){
message = system_getMsg();
do {
handle_msg(message)
} while (message != quit && time < limitTime);
}
run loop使应用程序处于不停的接收事件,处理事件阶段,直到收到退出循环的命令或者达到超时时间。其中事件既可以是应用间主动触发事件,也可以是由操作系统传递来的事件。
run loop的意义不仅仅是让应用保持运行不退出这么简单,因为单纯一个死循环是很耗CPU的,所以run loop还要做到当没有事件要处理的时候,就使应用休眠,不再占用CPU资源,而当有事件要处理的时候,应用能马上被唤醒以处理事件,处理完后继续休眠,让出CPU......如此循环就构成了run loop。
run loop跟现实生活中的扶梯很像 ,扶梯不停的循环,把人运往他处, 乘梯的人是一个个事件,当没有人乘坐时,扶梯会减速,甚至会停止 以避免浪费电能和消耗设备,而当有人乘坐时,扶梯又会被马上唤醒,以原速继续托运人。run loop也是这个样子。
狭义上说,run loop是一个对象,是管理并实现运行循环的对象。通过它,以及一些列系统封装好的API。我们可以操作控制run loop。例如,开启run loop,停止run loop,向run loop中添加observer...... Foundation 框架和 Core Foundation框架都实现了run loop Api,都可以使用。
总之,run loop主要就是一种机制,消息循环机制。当有事件时候,app处理事件,当没有事件要处理时候,app进入休眠状态,让出CPU,同时等待后续事件到达。一直这样循环,直到app被用户手动关闭,或者被系统kill。下一篇文章将结合run loop源码,深入理解run loop的构成与原理