Run Loop剖析
Run Loop接收输入事件来自两种不同的来源:输入源(input source)和定时源(timer source)。
输入源传递异步事件,通常消息来自其他线程或程序。
定时源则传递同步事件,发生在特定时间或者重复的时间间隔。
输入源
输入源异步的发送消息给你的线程。事件来源取决于输入源的种类:基于端口的输入源和自定义输入源。
基于端口的输入源监听程序相应的端口。自定义输入源则监听自定义的事件源。
两类输入源区别在于如何显示:基于端口的输入源由内核自动发送,而自定义的则需要人工从其他线程发送。
Run Loop在你要和线程有更多的交互时才需要,比如以下情况:
- 使用端口或者自定义输入源和其他线程通信。
- 使用线程的定时器。
- Cocoa中使用任何performSelector...方法。
- 使线程周期性工作。
使用Run Loop对象
Run Loop对象提供了添加输入源,定时器和run loop的观察者以及启动run loop的接口。
每个线程都有唯一的与之关联的run loop对象。在Cocoa中,该对象是NSRunLoop类的一个实例。
获得Run Loop对象
- Cocoa程序中,使用NSRunLoop的currentRunLoop类方法来检索一个NSRunLoop对象。
配置Run Loop
在你在辅助线程运行Run Loop之前,你必须至少添加一输入源或定时器给它。
除了安装源,你也可以添加Run Loop观察者来监视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程序中使用NSTimer类方法创建并调配一个定时器。
- (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo
- (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo
上述方法创建了定时器并以默认模式把它们添加到当前线程的run loop.
也可以手工创建NSTimer对象,并通过NSRunLoop的addTimer:forMode:把它添加到runloop.