Run Loop观察者
源是合适的同步或异步事件发生时触发,而run loop观察者则是在run loop本身运行的特定时候触发。你可以使用run loop观察者来为处理某一特定事件或是进入休眠的线程做准备。你可以将run loop观察者和以下事件关联:
Run loop入口
Run loop何时处理一个定时器
Run loop何时处理一个输入源
Run loop何时进入睡眠状态
Run loop何时被唤醒,但在唤醒之前要处理的事件
Run loop终止
你可以给run loop观察者添加到Cocoa和Carbon程序里面,但是如果你要定义观察者并把它添加到run loop的话,那就只能使用Core Fundation了。为了创建一个run loop观察者,你可以创建一个CFRunLoopObserverRef类型的实例。它会追踪你自定义的回调函数以及其它你感兴趣的活动。
和定时器类似,run loop观察者可以只用一次或循环使用。若只用一次,那么在它启动后,会把它自己从run loop里面移除,而循环的观察者则不会。你在创建run loop观察者的时候需要指定它是运行一次还是多次。
关于如何创建一个run loop观察者的实例,参阅“配置run loop”部分。关于更多的相关信息,参阅CFRunLoopObserver Reference。
Run Loop的事件队列
每次运行run loop,你线程的run loop对会自动处理之前未处理的消息,并通知相关的观察者。具体的顺序如下:
通知观察者run loop已经启动
通知观察者任何即将要开始的定时器
通知观察者任何即将启动的非基于端口的源
启动任何准备好的非基于端口的源
如果基于端口的源准备好并处于等待状态,立即启动;并进入步骤9。
通知观察者线程进入休眠
将线程置于休眠直到任一下面的事件发生:
某一事件到达基于端口的源
定时器启动
Run loop设置的时间已经超时
run loop被显式唤醒
通知观察者线程将被唤醒。
处理未处理的事件
如果用户定义的定时器启动,处理定时器事件并重启run loop。进入步骤2
如果输入源启动,传递相应的消息
如果run loop被显式唤醒而且时间还没超时,重启run loop。进入步骤2
通知观察者run loop结束。
因为定时器和输入源的观察者是在相应的事件发生之前传递消息,所以通知的时间和实际事件发生的时间之间可能存在误差。如果需要精确时间控制,你可以使用休眠和唤醒通知来帮助你校对实际发生事件的时间。
因为当你运行run loop时定时器和其它周期性事件经常需要被传递,撤销run loop也会终止消息传递。典型的例子就是鼠标路径追踪。因为你的代码直接获取到消息而不是经由程序传递,因此活跃的定时器不会开始直到鼠标追踪结束并将控制权交给程序。
Run loop可以由run loop对象显式唤醒。其它消息也可以唤醒run loop。例如,添加新的非基于端口的源会唤醒run loop从而可以立即处理输入源而不需要等待其他事件发生后再处理。