Runloop循环机制

   今天看了下前天发的博文<函数响应式编程(FRP)框架--ReactiveCocoa>的阅读量,小编有点惊呆了,两天有这么多的读者能阅读我的博文,这对小编来说甚是激动,毕竟有段时间没更新博文了,于是,今天怀着激动的心情,小编决定坐下来跟大家好好谈谈Runloop的机制,让我们正式进入正题吧。

  关于 Runloop,从字面上去理解呢,看上去不是就运行的循环吗?哈哈,确实,Runloop说白了就是一种循环,不过它是一种比较高级的循环。那么或许你又会问,Runloop跟我们平时使用的while循环又有什么不一样呢?小编在这只能跟你说:莫慌,在这里,你的问题终将会解决的。接下来小编会谈到的。

  说起Runloop,可能你想起的可能更多是跟线程一起,的确如此,Runloop 是和线程紧密相关的一个基础组件,是很多线程有关功能的幕后功臣。尽管在平常使用中几乎不太会直接用到,但是呢理解 Runloop 有利于我们更加深入地理解 iOS 的多线程模型。

  上面谈及的 while 循环呢,其实它会导致 CPU 进入忙等待状态,而 Runloop 则是一种“闲”等待,当没有事件时,Runloop 会进入休眠状态,有事件发生时, Runloop 会去找对应的 Handler 处理事件。Runloop 可以让线程在需要做事的时候忙起来,不需要的话就让线程休眠。引用一张苹果官方文档的图,大体说明了 Runloop 的工作模式:

   

  从上图我们可以了解 Runloop 在线程中的作用:从 input sources 和 timer sources 接受事件,然后在线程中处理事件。接下来将会从以下几个方面来谈谈Runloop机制。

Runloop 与线程

  Runloop 和线程其实是绑定在一起的。每个线程(包括主线程)都会有一个对应的 Runloop 对象。我们并不能自己创建 Runloop 对象,但是可以获取到系统提供的 Runloop 对象。主线程的 Runloop 会在应用启动的时候完成启动,其他线程的 Runloop 默认并不会启动,需要我们自己手动去启动。

Input Source 和 Timer Source

Input Source 和 Timer Source 这两个是 Runloop 事件的来源,Runloop从 input sources 和 timer sources 接受事件,其中 Input Source 又可以分为三类:

  • Port-Based Sources,系统底层的 Port 事件,例如 CFSocketRef ,在应用层基本用不到
  • Custom Input Sources,用户手动创建的 Source
  • Cocoa Perform Selector Sources, Cocoa 提供的 performSelector 系列方法,也是一种事件源

Timer Source 就是定时器事了,这个不难理解。

Runloop Observer

Runloop 通过监控 Source 来决定有没有任务要做,除此之外,我们还可以用 Runloop Observer 来监控 Runloop 本身的状态。 Runloop Observer 可以监控下面的 runloop 事件:

  • The entrance to the run loop.
  • When the run loop is about to process a timer.
  • When the run loop is about to process an input source.
  • When the run loop is about to go to sleep.
  • When the run loop has woken up, but before it has processed the event that woke it up.
  • The exit from the run loop.

Runloop Mode

在监视与被监视中,Runloop 要处理的事情还挺复杂的。为了让 Runloop 能专心处理自己关心的那部分事情呢,引入了 Runloop Mode 概念。

 

Runloop Mode 实际上是 Source,Timer 和 Observer 的集合,不同的 Mode 把不同组的 Source,Timer 和 Observer 隔绝开来。Runloop 在某个时刻只能运行在一个 Mode 下,处理这一个 Mode 当中的 Source,Timer 和 Observer。

苹果文档中提到的 Mode 有五个:

  • NSDefaultRunLoopMode
  • NSConnectionReplyMode
  • NSModalPanelRunLoopMode
  • NSEventTrackingRunLoopMode
  • NSRunLoopCommonModes
  iOS 中公开出来的只有 NSDefaultRunLoopMode 和 NSRunLoopCommonModes。 NSRunLoopCommonModes 实际上是一个 Mode 的集合,默认包括 NSDefaultRunLoopMode 和 NSEventTrackingRunLoopMode。
   与 Runloop 相关的实例

我们在日常开发中,与 RunLoop 接触得最多的可能就是通过 NSTimer 了。一个 Timer 一次只能加入到一个 RunLoop 中。我们日常使用的时候,通常就是把 Timer加入到当前的 runLoop 的 default mode 中,而 ScrollView 在用户滑动时,主线程 RunLoop 会转到 UITrackingRunLoopMode 。而这个时候, Timer 就不会运行。那么如何解决这个问题呢?

有如下两种解决方案:

  • 第一种: 设置RunLoop Mode,例如NSTimer,我们指定它运行于 NSRunLoopCommonModes ,这是一个Mode的集合。注册到这个 Mode 下后,无论当前 runLoop 运行哪个 mode ,事件都能得到执行。
  • 第二种: 另一种解决Timer的方法是,我们在另外一个线程执行和处理 Timer 事件,然后在主线程更新UI。

 比如在 AFNetworking 3.0 中,就有相关的代码,如下:

- (void)startActivationDelayTimer {
    self.activationDelayTimer = [NSTimer
                                 timerWithTimeInterval:self.activationDelay target:self selector:@selector(activationDelayTimerFired) userInfo:nil repeats:NO];
    [[NSRunLoop mainRunLoop] addTimer:self.activationDelayTimer forMode:NSRunLoopCommonModes];
}

这里就是添加了一个计时器,由于指定了 NSRunLoopCommonModes,所以不管 RunLoop 出于什么状态,都执行这个计时器任务。

 好啦,今天谈的Runloop就到这里啦,有疑问的读者可以留下评论,小编会很及时回复,分享是一种乐趣,交流是一种享受,也可以关注我哦。
































  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值