ios Runloop 详细解析

        关于Run Loops看了很多大神文章,还是有点云里雾里,所以有时间感觉还是有必要从概念入手,仔细啃一遍官方文档。一起学习理解,有错误的地方请指正。

RunLoop-概念

      Run Loops是一个事件处理循环机制,用于整合处理接收到的事件,它是IOS与线程相关的基础架构的一部分。Run Loops的主要职责是当有事件需要处理的时候唤醒线程进行处理,反之使线程处于休眠状态。

      每个线程都有一个相关联的Run Loops对象,我们的程序不需要自己去创建。 Cocoa and Core Foundation都提供了相应的接口帮助我们配置以及管理与线程相关联的Run Loops,主线程的run loop是随着程序启动的时候已经自动配置和启动的,其他线程的runloop需要我们自己手动启用。CFRunLoop 是Core Foundation 库提供的runloop接口用C/C++实现的,是线程安全的,NSRunLoop是Foundation提供的接口用OC实现,是对CFRunLoop的封装,不是线程安全的,所以我们用NSRunLoop的对象处理runloop的时候需要避免在多线程处理。

RunLoop-原理

       Run Loops是一个循环,线程启动,借助runloop响应处理输入的事件,runloop的本质就是借助while或者for控制语句实现的,在循环里面我们使用run loop 的对象接收事件以及执行处理操作。

        Run Loops接收两种不同的事件源,Input sourcesTimer sources。Input sources发送异步事件,比如线程之间的通信或者APP之间的通信。Timer sources发送同步事件,比如在预定的时间发生的事件或者重复发生的事件。对于Input sources我们可以通过Core Foundation 框架提供的接口注册runloop的观察者,当runloop的行为发生改变我们可以收到通知,以此做一些需要的操作。runloop处理这两种事件源都是按照程序指定的流程处理,如图所示:

ios Runloop 详细解析_第1张图片

RunLoop-模式

       runloop模式是Input sourcesTimer sources事件集合以及注册观察runloop的观察者集合。我们运行runloop都需要指定对应的模式,当我们指定某种模式,只有该模式相关联的事件源会被监听并且允许其传递事件(类似的只有观察了对应模式的runloop才会收到,runloop的处理进度)。其他模式的事件源只能等待适合的模式才能向runloop传递事件。Core Foundation框架提供了五种模式(NSDefaultRunLoopMode,NSConnectionReplyMode,NSModalPanelRunLoopMode,NSEventTrackingRunLoopMode,NSRunLoopCommonModes),我们这里只介绍三种常用的,如果有需要下次再更新。

1.NSDefaultRunLoopMode:默认模式,大多数时候我们使用这个模式启动runloop和配置input sources,比如我们创建的定时器默认就是该模式。

2.NSEventTrackingRunLoopMode:字面意思就是事件追踪模式,该模式监听鼠标拖动(手指拖动)以及其他类型的用户交互追踪。比如当我们滑动表的时候就会触发该模式下的runloop。

3.NSRunLoopCommonModes:这个模式是一个常用模式的组合,在Foundation框架下该模式包含NSDefaultRunLoopMode和NSEventTrackingRunLoopMode,在Core Foundation下只包含NSDefaultRunLoopMode,我们可以使用CFRunLoopAddCommonMode函数将自定义模式添加到该集合。指定这种模式就相当于指定了该模式组合下的所有模式。

我们何时需要使用RunLoop?

   你可能用到runloop的地方是当你创建子线程的时候,但是并不是所有的子线程都需要开启runloop,比如你开始一个子线程执行一个复杂耗时的任务或者一个预先设定好的任务,此时我们都不需要开启runloop,很多时候runloop是用于线程间的通讯的。官方总结了以下几点我们会使用到runloop的地方:

1.当我们使用端口或者自定义的input sources与其他线程交互的时候。

2.在线程中使用定时器。

3.在程序中使用任何的performSelector… 方法。

4.让线程执行定期的任务

RunLoop使用注意事项

        开启runloop有三种方法,1.不加任何限制的开启,2设定一个限定时间,3.指定一种模式。一个runloop至少需要监视一个input source或者一个定时器,否则runloop会立即退出。第一种开启的方法是最简单的但是也是最不可取的,因为这种方法是不可控制。第二种方法和第三种方法可以混合使用,而且是比较推荐使用的。

       退出runloop有两种方式:1.当我们以限定时间开启一个runloop时,时间结束,runloop就会退出,2.手动停止,调用Core Foundation提供的CFRunLoopStop函数。虽然移除input source或者定时器会使runloop退出,但是很多时候,我们的代码不能正真的移除input source或者定时器,而这些会阻止runloop退出。

你可能感兴趣的:(ios Runloop 详细解析)