iOS开发RunLoop
最近处于离职状态,时间也多了起来,但是学习还是不能放松,今天总结一下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的更多相关文章
- iOS开发RunLoop学习:一:RunLoop简单介绍
一:RunLoop的简单介绍 #import "ViewController.h" @interface ViewController () @end @implementatio ...
- iOS开发RunLoop学习:四:RunLoop的应用和RunLoop的面试题
一:RunLoop的应用 #import "ViewController.h" @interface ViewController () /** 注释 */ @property ( ...
- iOS开发-Runloop详解(简书)
不知道大家有没有想过这个问题,一个应用开始运行以后放在那里,如果不对它进行任何操作,这个应用就像静止了一样,不会自发的有任何动作发生,但是如果我们点击界面上的一个按钮,这个时候就会有对应的按钮响应事件 ...
- iOS开发 - RunLoop理解
RunLoop概念 运行循环,一个 run loop 就是一个事件处理的循环,用来不停的调度工作以及处理事件 作用 保持程序的持续运行 监听处理App中的各种事件(触摸事件,定时器事件,selecto ...
- 玩转iOS开发 - Runloop 具体解释
Runloop 具体解释
- iOS开发RunLoop学习:三:Runloop相关类(source和Observer)
一:RunLoop相关类: 其中:source0指的是非基于端口por,说白了也就是处理触摸事件,selector事件,source1指的是基于端口的port:是处理系统的一些事件 注意:创建一个Ru ...
- iOS开发-- RunLoop的基本概念与例子分析
看了一下,上一篇貌似5个月前的
- iOS开发 - 啰嗦讲解 Runloop
写在前面的 为什么要了解 RunLoop?如果你想成为一个高级iOS开发工程师,那这是你必须了解的东西,他能帮助你更好的理解底层实现的原理,可以利用它的特性做出一些高效又神奇的功能.RunLoop这个 ...
- iOS开发 底层抛析运行循环—— RunLoop
http://blog.csdn.net/zc639143029/article/details/50012527 一.RunLoop基本概念 概念:程序的运行循环,通俗的来说就是跑圈. 1. 基本作 ...
随机推荐
- Centos6.5 mysql折腾记
1.yum安装mysql [root@localhost ~]# yum -y install mysql-server 安装结果 Installed: mysql-server.x86_64 0:5 ...
- 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 ...
- SQL SERVER 判断是否存在并删除某个数据库、表、视图、触发器、储存过程、函数
-- SQL SERVER 判断是否存在某个触发器.储存过程 -- 判断储存过程,如果存在则删除IF (EXISTS(SELECT * FROM sysobjects WHERE name='proc ...
- Kafka 0.10 SocketServer源代码分析
1概要设计 Kafka SocketServer是基于Java NIO来开发的,采用了Reactor的模式,其中包含了1个Acceptor负责接受客户端请求,N个Processor负责读写数据,M个H ...
- C# 6 与 .NET Core 1.0 高级编程 - C# 6 改进
个人原创译文,转载请注明出处.有不对的地方欢迎指出与交流. 英文原文:Professional C# 6 and .NET Core 1.0 - What's New in C# 6 C# 6 改进 ...
- 我的Java笔记
第一章 一 计算机程序:一系列有序的指令集合. 二 java语言分为三个领域 javaSE java技术核心(桌面应用程序)qq 百度云 javaEE 企业版(面向internet的应用程序)京东 淘 ...
- NodeJS Stream 五:双工流
双工流就是同时实现了 Readable 和 Writable 的流,即可以作为上游生产数据,又可以作为下游消费数据,这样可以处于数据流动管道的中间部分,即 rs.pipe(rws1).pipe(rws ...
- HDU 2186 悼念512汶川大地震遇难同胞——一定要记住我爱你
悼念512汶川大地震遇难同胞——一定要记住我爱你 Time Limit: 1000/1000 MS (Java/Others) Memory Limit: 32768/32768 K (Java ...
- ajax提交File文件
<script type="text/javascript"> $(function() { $("input[name='image'] ...
- 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. ...