iOS RunLoop

一、什么是RunLoop

iOS的RunLoop简单来说就是一个运行循环,在需要的时候运行,在不需要的时候进行休眠,节省CPU资源。

下面是苹果官方文档的一张解释RunLoop的图示,大概展示了RunLoop的工作原理。

苹果官方文档RunLoop图示

从上面的图可以看出RunLoop的大概工作原理,当接收到Input sources 或者 Timer sources时就会交给对应的处理方去处理。当没有事件消息传入的时候,RunLoop就进入休眠状态。runloop处于监视与被监视的状态中,要处理很多复杂的事件,下面会详细介绍runloop的组成。

input source 和 timer source

input source 和 timer source 都是runloop的事件源,其中input source又可以分为三类:

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

Timer Source 也就是定时器事件。

RunLoop Observer

runloop observer是runloop本身的监视器,它可以监视runloop自身的状态。runloop observer 可以监视下面的runloop事件

  • The entrance to the run loop. (进入循环)
  • When the run loop is about to process a timer.(循环将要处理 timer 事件源)
  • When the run loop is about to process an input source.(循环将要处理input source事件源)
  • When the run loop is about to go to sleep.(循环将要进入休眠)
  • When th run loop has woken up,but before it has processed th event that woke it up.(循环已经被唤醒,但是还没有处理唤醒该循环的事件)
  • The exit from th run loop.(退出循环)

Runloop Mode

先上一个图

Runloop Mode 实际上是Source,Timer 和Observer的组合。不同的Mode讲不同组的Source, Timer,Observer打包与其他Mode的内部成员隔绝开来。这样Runloop在某个时刻就只能跑在一个Mode下,专心处理该Mode下的Source,Timer和Observer。

苹果官方文档中提到的Mode有5种,分别是:

  • NSDefaultRunLoopMode
  • NSConnectionRepLyMode
  • NSModalPanelRunLoopMode
  • NSEventTrackingRunLoopMode
  • NSRunLoopCommonModes

iOS 中公开暴露出来的只有 NSDefaultRunLoopMode 和 NSRunLoopCommonModes。 NSRunLoopCommonModes 实际上是一个 Mode 的集合,默认包括NSDefaultRunLoopMode 和 NSEventTrackingRunLoopMode。

当然,RunLoop Mode不止上面提到的5种,我们来看下系统开启后,都默认注册了哪些Mode。

  • kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
  • UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
  • UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
  • GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
  • kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode

二、RunLoop和线程有什么关系

  • runloop的作用就是管理线程,当线程的runloop开启后,县城就会在执行完任务后进入到休眠状态,随时等待新的事件源进入,而不是退出。

  • runloop和线程一一对应,每个线程只有一个runloop。线程在创建的时候并没有创建runloop,需要手动创建(主线程除外)。iOS中没有创建runloop的方法,是通过获取时懒加载实现的。只能在线程内部获取改线程的runloop(主线程除外)。

三、iOS中提供的RunLoop对象及其访问方法

RunLoop对象

iOS中提供了两个RunLoop对象

  • CFRunLoopRef : CorFoundation框架内,提供纯C函数的API,所有这些API都是线程安全的。
  • NSRunLoop : 基于CFRunLoopRef的封装,提供了面向对象的API,但是这些API不是线程安全的。

获取RunLoop对象。

苹果不允许直接创建runloop,只提供了获取Runloop的函数:

  • Core Foundation

    CFRunLoopGetCurrent() //获取当前线程的RunLoop对象
    CFRunLoopGetMain() //获取主线程的RunLoop对象
  • Foundation

    [NSRunLoop currentRunLoop] //获取当前线程的RunLoop对象
    [NSRunLoop MainRunLoop] //获取主线程的RunLoop对象

RunLoop相关的类

Core Foundation中关于RunLoop的5个类

  1. CFRunLoopRef

    • 用来获取当前的RunLoop和主RunLoop
  2. CFRunLoopModeRef

    • RunLoop的运行模式,一个RunLoop包含若干个Mode;
    • 每个Mode包含若干个 Source/Timer/Observer,每次RunLoop启动时,只能制定一个Mode运行,这个Mode被称之为CurrentMode;
    • 如果需要切换Mode,只能退出RunLoop,重新制定一个Mode进入;
    • 这样可以分隔开不同组的Source/Timer/Observer互不影响。
  3. CFRunLoopSourceRef
    • CFRunLoopSourceRef 是事件源
    • 按照官方文档分类:
      • Port-Based Sources(基于端口,跟其他线程交互,通过内核发布的消息);
      • Custom Perform Selector Sources(自定义);
      • Cocoa Perform Selector Sources(PerformSelector方法)
    • 按照函数调用栈的分类
      • Source0:非基于Port
      • Source1:基于Port
  4. CFRunLoopTimerRef
    • CFRunLoopTimerRef是基于时间的触发器
    • 基本上说的就是NSTimer(CADisplayLink也是加到RunLoop),它受RunLoop Mode的影响。
  5. CFRunLoopObserveRef
    • CFRunLoopObserverRef是观察者类,负责监听RunLoop的状态改变;
    • 可以监视上面 RunLoop Observer中提到的几个状态变化。

四、Runloop的实际应用

  • 在线程中使用timer

    这应该是最常见的runloop的应用。一个NSTimer一次只能加入到一个runloop中。我们日常使用的时候,通常是加入到当前的runloop的default mode中,而scrollView在用户滑动的时候,主线程的runloop就会跳转到UITrackingRunLoopMode。而这个时候 timer就不会运行。针对这种情况有两种解决方案:

    • 设置Runloop Mode,例如NSTimer,我们指定它运行在NSRunLoopCommonModes,这是一个Mode的集合。注册到这个Mode下后,无论当前的runloop运行哪个Mode,事件都能得到执行。
    • 另一种解决timer的办法就是,我们在另一个线程执行和处理timer事件,然后在主线程更新UI。
  • 将有频繁操作的回调指定到固定的线程中执行。这样可以减少线程创建和销毁的开销。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值