iOS 的RunLoop初识

来源:互联网 发布:linux启动ntp服务 编辑:程序博客网 时间:2024/04/29 07:20

     想多了解下iOS的运行机制,所以搜了搜runloop的资料看看,发现看了好几篇都没有看懂这个runloop用来干嘛的。说到runloop是用来做什么的,只有一句话:

下来是Run Loop的使用场合:
1. 使用port或是自定义的input source来和其他线程进行通信
2. 在线程(非主线程)中使用timer
3. 使用 performSelector…系列(如performSelectorOnThread, …)
4. 使用线程执行周期性工作

却没有地方针对每个方面说一下,到底这四个方面是怎么用的。其实我不是关心这四个功能怎么实现,我关心的是在这些功能里面,runloop起了什么作用。

  我很生气,看到一片片文章人云亦云,这些人怎么都不自己多思考一下?

  我的思维习惯是,对于一个新的待了解的东西,我需要先知道它是用来干什么的、它在什么样的环境下使用并且起到了什么样的作用,然后才是去分析它的结构属性,具体怎么使用。首先没有对一个东西的定位,怎么去处理它的细节问题?

  查了一些资料,只了解了一点:

1、RunLoop本质上是一个消息处理的机制,它不断的循环运行,判断线程中是否有需要处理的消息。这个理解来源于有篇文章说的一个例子:手机上一个程序开启,当你不去动它时,这个程序就好像死了一样,但是只要你触碰一个按钮,它就会马上响应,就好像程序一直处于待命状态。这就是主线程的runloop一直在运行,监测事件。

2、有了这个理解,接下来就会想runloop会监测哪些事件。当你知道了它监测哪些事件,也就知道了在什么情况下需要使用开启runloop。回答这个问题就是上面蓝色那段话。因为主线程的runloop是默认开启的,所以我们一般用到像:

[self performSelector:@selector(delay) withObject:nil afterDelay:1];
这样的方法,系统都会自然执行。但这个方法得以执行,实际需要靠主线程的runloop的,但是我们很容易忽视了它。对于这个方法,文档有很好的解释:

This method sets up a timer to perform the aSelector message on the current thread’s run loop. The timer is configured to run in the default mode (NSDefaultRunLoopMode). When the timer fires, the thread attempts to dequeue the message from the run loop and perform the selector. It succeeds if the run loop is running and in the default mode; otherwise, the timer waits until the run loop is in the default mode.

If you want the message to be dequeued when the run loop is in a mode other than the default mode, use theperformSelector:withObject:afterDelay:inModes: method instead. If you are not sure whether the current thread is the main thread, you can use theperformSelectorOnMainThread:withObject:waitUntilDone: or performSelectorOnMainThread:withObject:waitUntilDone:modes: method to guarantee that your selector executes on the main thread. To cancel a queued message, use thecancelPreviousPerformRequestsWithTarget: or cancelPreviousPerformRequestsWithTarget:selector:object: method.

这个方法会构建一个计时器,把aSelector message运行在当前线程的runloop上。这个计时器配置为使用默认的模式运行。当计时器fires(NSTimer的fire方法是启动计时器,不过这里貌似是当计时器的时间到了,比如这里延时1秒,应该是计时器开启之后一秒)时,当前线程又会常识从runloop上面获取message,然后执行方法。如果当前runloop是以默认模式运行就会成功。然后说明了如果不是使用默认模式、不确定当前是否主线程等情况下使用同类型的哪些其他方法。

  所以这个过程中需要runloop做一个中介,在调用performSelector时runloop会保存要调用的方法信息,然后在时间到了,当前线程会从runloop里面获取方法信息,然后调用。所以需要runloop的参与,需要开启runloop。
  关于文档里面的aSelector message,我的理解是,使用SEL来调用方法,不是直接调用方法,是发送消息给方法的调用者(target),让它去执行方法。所以关键的东西是这个消息,这个消息至少应该保存方法的调用者(target)和方法本身的信息,可能还有参数。所以才会有aSelector message“方法消息”这么样的词,然后保存进runloop中的应该也是这么样一个消息。而runloop在它循环运行的过程中,会不断监测类似的消息,在特定的时机调用。

  可能有不正确的地方,仅提供一种理解,欢迎指正。

  关于其他的输入源,也就是第一种使用场合,可以参考:这篇文章 的2.1.1输入源的部分。


0 0