中高级iOS必备知识点之 RunLoop(一)

RunLoop学习起来是很抽象,也不好理解,所以一定多看几次,多学学才能学好!这也是中高级iOS必须掌握的知识点,面试中经常遇到.

什么是 RunLoop?

Run 表示运行,Loop 表示循环。结合在一起就是运行循环的意思。RunLoop就是在程序运行过程中循环做一些事情.

RunLoop的应用范畴有哪些?

定时器(Timer)、PerformSelector

GCD Async Main Queue

事件响应、手势识别、界面刷新

网络请求

AutoreieasePool

上面这些底层都是RunLoop在支撑,说白了,如果没有RunLoop支撑,上面的这些都无法实现.

如果没有RunLoop会发生什么呢?像我们的命令行项目,创建出来默认就是没有RunLoop,请看下图

因为没有RunLoop,程序执行到第13行的时候,就会自动退出.

而我们iOS项目的main函数里面都有UIApplicationMain(argc, argv,nil, appDelegateClassName);这个代码,这里就是创建了一个主线程的RunLoop,所以我们程序不会退出,一直在运行中.我们可以大致写一下main函数里面的伪代码如下:

retVal这个等于0,当没有事件处理的时候,RunLoop就会sleep就是类似睡觉,一旦有事件需要处理,比如点击、刷新事件等process_message就会去处理这个事件,处理完了继续休息,retVal=0,程序就会一直执行,不会退出,这就是RunLoop作用.

RunLoop的基本作用

1.保持程序的持续运行

2.处理App中的各种事件(比如触摸事件、定时器事件等)

3.节省了CPU资源,提高程序性能:该做事时做事,该休息时休息

...

获取RunLoop对象

iOS中有2套API来访问和使用RunLoop :

Foundation : NSRunLoop  (OC语言里面的)

Core Foundation : CFRunLoopRef  (C语言里面的)

NSRunLoop和CFRunLoopRef都代表着RunLoop对象

NSRunLoop是基于CFRunLoopRef的一层OC包装

CFRunLoopRef是开源的.(CFRunLoopRef参考链接)

其实我们很多都是由OC包装出来的,请看下面:

获取当前的RunLoop

获取当前RunLoop和主线程RunLoop

获取RunLoop

这里注意,地址不一样,因为NSRunLoop是对CFRunLoopDef做了一层包装,你可以用OC的NSLog("%@",[NSRunLoop MainRunLoop])获取对比一下,它的地址就是C语言获取的地址.主线程只有一个RunLoop.

RunLoop与线程

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

RunLoop保存在一个全局的Dictionary里,线程作为key,RunLoop作为value

线程刚创建的时候并没有RunLoop对象,RunLoop会在第一次获取它时创建

RunLoop会在线程结束时销毁

主线程的RunLoop已经自动创建,子线程默认没有开启RunLoop.

源码窥探看一下:CFRunLoopGetCurrent

由于源码不能像objc直接打开,我们把它拉到项目中查看.

从字典也能看出来是一对一的关系.而且确实是第一次获取的时候是空的,然后再去创建这个RunLoop.

那我们就继续来了解RunLoop内部的数据结构,到底是怎么工作的.

RunLoop相关的类

Core Foundation中关于RunLoop的5个类

1.CFRunLoopRef

2.CFRunLoopModeRef

3.CFRunLoopSourceRef

4.CFRunLoopTimerRef

5.CFRunLoopObserverRef

再看下CFRunLoopRef的底层源码:

就是上面这个结构体,我们用到的可能就是红色这些.pthread是线程,每个runloop都会保存这个东西.最后面那个_modes,这个是个集合来着,CFMutableSetRef我们能想到我们自己用的set也是一个集合来着,比如NSMutableSet也是一个集合,所以这个_modes里面是存着一堆的mode.

这个mode就是CFRunLoopModeRef类型,所以里面存储一堆的CFRunLoopModeRef类型的mode.

而_currentMode也是CFRunLoopModeRef这个类型,所以我们很容易得出一个结论:

一个RunLoop对象里面有一堆的mode,也就是存在_modes里面,里面只有一个是_currentMode.

我们再窥探一下源码,看下mode里面存储的是什么?

所以我们来个总结的图:

RunLoop有很多种模式,对应的_currentMode只有一种.

CFRunLoopModeRef

1.CFRunLoopModeRef它是代表RunLoop的运行模式

2.一个RunLoop包含若干个Mode,每个Mode又包含若干个Source0/Source1/Timer/Observer

3.RunLoop启动时只能选择其中一个Mode,作为currentMode

4.如果需要切换Mode,只能退出当前RunLoop,再重新选择一个Mode进入

5.不同组的Source0/Source1/Timer/Observer能分割开来,互不影响

6.如果Mode里面没有任何Source0/Source1/Timer/Observer,RunLoop会立马退出

如果只能在一种模式下运行,对性能什么的都有很大好处,比如我在滑动模式下,不考虑不滑动的模式,所以就不会卡顿,顺畅很多.还有注意的就是,它切换mode是在循环里面切换的,所以不会导致程序退出.

常见的mode有2种,其他情况很少见,所以掌握这两个一般都是没问题了

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

2.UITrackingRunLoopMode : 界面跟踪Mode,用于ScrollView追踪触摸滑动,保证界面滑动时不受其他Mode影响

RunLoop到底做哪些事?

RunLoop在不停执行的时候到底具体做了哪些事?其实是RunLoop在不停循环的时候,就是处理每个mode下的Source0、Source1、Timer、Observer这里面的事件,那我们就来看看这里面具体对应的到底是什么事件.

Source0

触摸事件、performSelector:onThread:

比如我们的touchbegin这个我们看下下面的代码:

Source1

基于Port的线程间的通信,系统事件的捕捉.

(两个线程之间相互传递消息的处理,系统事件捕捉,其实也包括触摸事件,只是把事件捕捉到以后传递给Source0).

Timer

NSTimer定时器,performSelector:withObject:afterDelay(这个方法的底层实现也就是NSTimer来实现的)

Observers

用于监听RunLoop的状态,UI的刷新(BeforeWaiting),Autorelease pool(BeforeWaiting)

(在RunLoop休眠之前都会去执行UI的刷新啊、Autorelease pool的释放等)

以上这些东西,完全就是我们平时开发中经常写的代码,比如设置背景色,设置frame等等.

由于RunLoop知识点比较多,如果写太多不利于大家的阅读和消化,所以其他内容放在后面介绍!

接下来我会继续介绍Runloop其他知识点.

如果觉得我写得对您有所帮助,请关注我,我会持续更新😄

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 202,905评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,140评论 2 379
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 149,791评论 0 335
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,483评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,476评论 5 364
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,516评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,905评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,560评论 0 256
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,778评论 1 296
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,557评论 2 319
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,635评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,338评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,925评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,898评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,142评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,818评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,347评论 2 342

推荐阅读更多精彩内容