最近处于离职状态,时间也多了起来,但是学习还是不能放松,今天总结一下RunLoop,RunLoop属于iOS系统层的东西,还是比较重要的。

一、什么是RunLoop

字面意思看是跑圈,也可以看作运行循环,我认为RunLoop是个强大的while循环,需要的时候可以将其唤醒工作,不需要的时候可以让其进行休眠节省资源。

那它又有什么作用呢,我总结主要有三点:(1)保持程序的持续运行(2)处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)(3)节省cpu资源,提高程序性能,该做事的时候做事,该休息的时候休息。举个例子,我们程序的入口main函数的UIApplicationMain函数内部久启动了一个RunLoop,所以UIApplicationMain函数一直没有返回,保证了程序的持续运行,默认启动的RunLoop是跟我们主线程相关联的。

二、RunLoop对象

iOS提供了两套API来访问和使用RunLoop:

NSRunLoop(Foundation层)

CFRunLoopRef(Core Foundation层)

三、RunLoop与线程

(1)每条线程都有唯一的一个与之对应的RunLoop对象。

(2)主线程RunLoop已经是创建好的了,子线程的RunLoop需要主动创建。

(3)RunLoop在第一次获取时创建,在线程销毁时销毁,可以将其理解为线程中的变量。

四、RunLoop对象的获取方式

基于Foundation:

    [NSRunLoop currentRunLoop];//或得当前线程的RunLoop对象
[NSRunLoop mainRunLoop];//获得主线程的RunLoop对象

基于Core Foundation:

    CFRunLoopGetCurrent();//或得当前线程的RunLoop对象
CFRunLoopGetMain();//获得主线程的RunLoop对象

五、RunLoop相关类

Core Foundation中关于RunLoop的五个类:

(1)CFRunLoopRef

(2)CFRunLoopModeRef

(3)CFRunLoopSourceRef

(4)CFRunLoopTimerRef

(5)CFRunLoopObserverRef

RunLoop中可以有多个Mode,是RunLoop的重要组成部分,也是RunLoop中不可缺少的部分,可以理解为如果RunLoop中没有Mode那么RunLoop是跑不起来的。所以说它是不可缺少的部分。其中还包括Source,Timer,Observer。Timer是处理定时器的,Observer可以理解为对RunLoop的监听,不如RunLoop的开启或者休眠等等状态,Source表示所要处理的事情,比如说点击某个按钮处理一些事情都属于Source。我觉得有一点很重要,着重提一下,RunLoop的前提是有Mode,Mode的前提是有Source,Timer,Observer。

下面我们对RunLoop中的相关类做个详细介绍:

1.CFRunLoopModeRef

1.1 CFRunLoopModeRef

(1)CFRunLoopModeRef代表着RunLoop的运行模式。

(2)一个RunLoop包含若干个Mode,每个Mode又包含若干个Source,Timer,Observer。

(3)每次RunLoop启动时,只能指定其中一个Mode,这个Mode被称为CurrentMode。

(4)如果需要切换Mode,只能退出RunLoop,再重新指定一个Mode进入,这样做主要为乐分割Source,Timer,Observer让其互不影响。

1.2 系统会默认注册5个模式:

(1)kCFRunLoopDefaultMode:App默认的Mode,通常主线程是在这个Mode下运行的。

(2)UITrackingRunLoopMode:界面跟踪Mode,用于ScrollerView追踪触摸滑动,保证洁面滑动时不受其他Mode影响。

(3)UIInitializationRunLoopMode:在刚启动app时进入的第一个mode,启动完成后就不在使用。

(4)GSEventReceiveRunLoopMode:接受系统事件的内部mode,通常用不到。

(5)kCFRunLoopCommonModes:这是一个占位用的Mode,不是一种真正的mode,可以理解为不是一个确定的模式,既可以支持(1),又可以支持(2)。比如说我们在处理滑动事件定时器问题,这个mode就是很好的解决办法。

2.CFRunLoopSourceRef 事件源(输入源)

(1)Source0:非基于Port的,Port可以理解为我们的内核,比如说自定的一些事件,自己写的函数。

(2) Source1:基于Port的,相当于系统默认调的函数所产生的事件。

一个RunLoop的执行,在线程栈里会有一些我们看不到的函数是系统调用的。

3.CFRunLoopTimerRef

是基于时间的触发器,基本上说的就是NSTimer。

4.CFRunLoopObserverRef

CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变,可以监听的时间点有以下几个:

    typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << ), //即将进入RunLoop
kCFRunLoopBeforeTimers = (1UL << ), //即将处理Timer
kCFRunLoopBeforeSources = (1UL << ),//即将处理Sources
kCFRunLoopBeforeWaiting = (1UL << ),//即将进入休眠
kCFRunLoopAfterWaiting = (1UL << ), //刚从休眠中唤醒
kCFRunLoopExit = (1UL << ), //即将退出RunLoop
kCFRunLoopAllActivities = 0x0FFFFFFFU//监听RunLoop的所有情况
};

比如我们想要在按钮点击之前或者点击之后去做一些事情,我们想要监听到这样的一个状态,就可以使用CFRunLoopObserverRef,NSRunLoop中并没有提供CFRunLoopObserverRef的相关接口,我们要使用只能在Core Foundation中使用。

下面通过实例监测下RunLoop的执行状态:

    CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(CFAllocatorGetDefault(), kCFRunLoopAllActivities, YES, , ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity) {
NSLog(@"activity:%zd",activity);
}); CFRunLoopAddObserver(CFRunLoopGetCurrent(), observer, kCFRunLoopDefaultMode);
    CFRelease(observer);

打印结果:

-- ::17.268 testRunloop[:] activity:
-- ::17.268 testRunloop[:] activity:
-- ::17.268 testRunloop[:] activity:
-- ::17.270 testRunloop[:] activity:
-- ::17.270 testRunloop[:] activity:
-- ::17.270 testRunloop[:] activity:
-- ::17.270 testRunloop[:] activity:
-- ::17.271 testRunloop[:] activity:
-- ::17.271 testRunloop[:] activity:
-- ::17.271 testRunloop[:] activity:
-- ::17.271 testRunloop[:] activity:
-- ::17.271 testRunloop[:] activity:
-- ::17.271 testRunloop[:] activity:
-- ::17.271 testRunloop[:] activity:
-- ::17.276 testRunloop[:] activity:
-- ::17.276 testRunloop[:] activity:
-- ::17.276 testRunloop[:] activity:
-- ::17.277 testRunloop[:] activity:
-- ::17.277 testRunloop[:] activity:
-- ::17.286 testRunloop[:] activity:
-- ::17.286 testRunloop[:] activity:
-- ::17.286 testRunloop[:] activity:
-- ::17.287 testRunloop[:] activity:
-- ::17.287 testRunloop[:] activity:
-- ::17.287 testRunloop[:] activity:
-- ::17.287 testRunloop[:] activity:
-- ::17.743 testRunloop[:] activity:
-- ::17.744 testRunloop[:] activity:
-- ::17.745 testRunloop[:] activity:
-- ::17.745 testRunloop[:] activity:
-- ::18.699 testRunloop[:] activity:
-- ::18.699 testRunloop[:] activity:
-- ::18.700 testRunloop[:] activity:
-- ::18.700 testRunloop[:] activity:
-- ::22.999 testRunloop[:] activity:
-- ::23.000 testRunloop[:] activity:
-- ::23.000 testRunloop[:] activity:
-- ::23.000 testRunloop[:] activity:

现在看这张官方版的逻辑图是不是清晰多了,当然网友的力量是无尽的,下面再给大家展示张网友提供的逻辑图:

总结:RunLoop是与线程相对应的,每个线程都会有一个RunLoop,主线程的RunLoop默认是开启的,不需要我们处理,子线程的RunLoop是关闭的,需要我们自己开启,线程开启的时候RunLoop包含mode,而且必须在某个确定的模式下运行,mode里面的Source,Timer,Observer也需要有,还有包括它们所实现的功能等等。

以上就是对RunLoop的最基本的介绍,希望对大家的学习能有所帮助。

注:此文章为原创,转载请注明出处。

iOS开发RunLoop的更多相关文章

  1. iOS开发RunLoop学习:一:RunLoop简单介绍

    一:RunLoop的简单介绍 #import "ViewController.h" @interface ViewController () @end @implementatio ...

  2. iOS开发RunLoop学习:四:RunLoop的应用和RunLoop的面试题

    一:RunLoop的应用 #import "ViewController.h" @interface ViewController () /** 注释 */ @property ( ...

  3. iOS开发-Runloop详解(简书)

    不知道大家有没有想过这个问题,一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件 ...

  4. iOS开发 - RunLoop理解

    RunLoop概念 运行循环,一个 run loop 就是一个事件处理的循环,用来不停的调度工作以及处理事件 作用 保持程序的持续运行 监听处理App中的各种事件(触摸事件,定时器事件,selecto ...

  5. 玩转iOS开发 - Runloop 具体解释

    Runloop 具体解释

  6. iOS开发RunLoop学习:三:Runloop相关类(source和Observer)

    一:RunLoop相关类: 其中:source0指的是非基于端口por,说白了也就是处理触摸事件,selector事件,source1指的是基于端口的port:是处理系统的一些事件 注意:创建一个Ru ...

  7. iOS开发-- RunLoop的基本概念与例子分析

    看了一下,上一篇貌似5个月前的

  8. iOS开发 - 啰嗦讲解 Runloop

    写在前面的 为什么要了解 RunLoop?如果你想成为一个高级iOS开发工程师,那这是你必须了解的东西,他能帮助你更好的理解底层实现的原理,可以利用它的特性做出一些高效又神奇的功能.RunLoop这个 ...

  9. iOS开发 底层抛析运行循环—— RunLoop

    http://blog.csdn.net/zc639143029/article/details/50012527 一.RunLoop基本概念 概念:程序的运行循环,通俗的来说就是跑圈. 1. 基本作 ...

随机推荐

  1. Centos6.5 mysql折腾记

    1.yum安装mysql [root@localhost ~]# yum -y install mysql-server 安装结果 Installed: mysql-server.x86_64 0:5 ...

  2. Codeforces Round #257 (Div. 1)A~C(DIV.2-C~E)题解

    今天老师(orz sansirowaltz)让我们做了很久之前的一场Codeforces Round #257 (Div. 1),这里给出A~C的题解,对应DIV2的C~E. A.Jzzhu and ...

  3. SQL SERVER 判断是否存在并删除某个数据库、表、视图、触发器、储存过程、函数

    -- SQL SERVER 判断是否存在某个触发器.储存过程 -- 判断储存过程,如果存在则删除IF (EXISTS(SELECT * FROM sysobjects WHERE name='proc ...

  4. Kafka 0.10 SocketServer源代码分析

    1概要设计 Kafka SocketServer是基于Java NIO来开发的,采用了Reactor的模式,其中包含了1个Acceptor负责接受客户端请求,N个Processor负责读写数据,M个H ...

  5. C# 6 与 .NET Core 1.0 高级编程 - C# 6 改进

    个人原创译文,转载请注明出处.有不对的地方欢迎指出与交流. 英文原文:Professional C# 6 and .NET Core 1.0 - What's New in C# 6 C# 6 改进 ...

  6. 我的Java笔记

    第一章 一 计算机程序:一系列有序的指令集合. 二 java语言分为三个领域 javaSE java技术核心(桌面应用程序)qq 百度云 javaEE 企业版(面向internet的应用程序)京东 淘 ...

  7. NodeJS Stream 五:双工流

    双工流就是同时实现了 Readable 和 Writable 的流,即可以作为上游生产数据,又可以作为下游消费数据,这样可以处于数据流动管道的中间部分,即 rs.pipe(rws1).pipe(rws ...

  8. HDU 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你

    悼念512汶川大地震遇难同胞——一定要记住我爱你 Time Limit: 1000/1000 MS (Java/Others)    Memory Limit: 32768/32768 K (Java ...

  9. ajax提交File文件

    <script type="text/javascript">    $(function() {        $("input[name='image'] ...

  10. Linux-7.2+LNMP+zabbix-3.2.1

    LNMP+zabbix-3.2.1 一.zabbix服务端部署 1.解压 yum –y install bzip2 tar -xf nginx-1.10.1.tar.gz tar -xf php-5. ...