说到RunLoop,无论从项目代码或者网上都会有以下这段代码:
while (!_isFinish)
{
NSRunLoop *runloop = [NSRunLoop currentRunLoop];
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
}
究竟[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]干啥的?
本文本最重要的是要说明白这个事情!准备好开始了.
对于single view application的应用程序,UIApplicationMain()方法在这里不仅完成了初始化我们的程序并设置程序Delegate的任务,而且随之开启了主线程的Run Loop, 开始接受处理事件。
从简单开始,通过监听runloop状态,查看进入程序什么都不干,runloop会干点啥。
监听代码如下:
runLoopActivityStringWithActivity函数只是简单的把值转换成对应的文本方便查看。
打印结果如下:
log出来CFRunLoopActivity对应着别人简化runloop源码逻辑看,本文其它log也可
以对着看。
可知道:程序在经过了一系列变化后进入了休眠状态。
然后在viewController里加入个按钮button one,响应代码如下:
点击后打印结果:
主线程被换醒,然后处理按钮事件,接着过了一阵子就会从新进入休眠,等待下一事件。
继续往下,我又加了一个button two。并把代码修改成如下,大家都知道,点击了
button one 后就进入了死循环,点击button two 是不起作用的。这里就不上Log了。
但是把button one 代码改成下面这样,就算button one代码没有执行完,同样可以
在主线程响应button two的事件。究竟
[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
做了什么事情呢?
此时打印出来的log如下:
从log中看到并没有打印出one button End.说明one button 还没有执行完。
但是我们可以看到one button before和after RunLoop被打印了好几次,并且CFRunLoopActivity
打印出来好几次1和128.说明RunLoop是有退出和重新进入的。不是说主线程的runLoop不会退出的吗?
难道打出来的不是主线程的runLoop?下面就慢慢说明白这些东西
为了方便理解,我会把启动时应用给我们创建的RunLoop叫做RunLoop对象,它会一直循环着简化
runloop源码的逻辑。可以这样说RunLoop对象创建了一个循环,这个循环可以在有事件发生里处理
事件,没事发生就会休眠,等待事件发生。那为什么开始没改代码时那种情况为什么响应不了button two的事件呢,那是因为处理button one事件没还返回,系统给我们创建的这个循环并不能往下走了所以处理不了button two。而修改代码后,[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]其实是为RunLoop对象创建了个新的循环。一次循环只会打有一个kCFRunLoopEntry和kCFRunLoopExit,中间的CFRunLoopActivity状态则要看情况而定,如有哪个输入源等。到达kCFRunLoopExit表明这个循环要退出。由于while中一直为true,循环会不停被启动。[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]创建的循环我叫它子循环,button two 事件其实是在这个子循环里被处理。所以RunLoop对象的循环可以有多个,并且是嵌套的。事件处理会被嵌套最深的那个子循环处理。为了证实这个说法继续加了个button three,并把button two 代码修改,代码如下
连续点击button one two there.在three中打个断点。调用栈如下:
很明显看到,button two的事件是在one中创建的子循环执行,而button three的事件是在two中创建的子
循环执行。
总结:
1、[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]其实是为线程创建
一个循环,如果线程已经有,创建的是一个子循环。
2、通过[runloop runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]]创建的循环过一段时间或
马上返回,这取决于输入源及系统的调度。所以用while进行不断驱动,不停创建循环。
3、我们看到日志打印出kCFRunLoopExit是子循环的exit.