源码解读RunLoop,理解以后面试必加分

继上一篇博客

中高级iOS必备知识点之RunLoop(一)继续介绍

RunLoop的状态

首先我们去RunLoop的源码去查看它有几种状态,如下图:

它一共有上面的这几种个状态

/* Run Loop Observer Activities */

typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {

kCFRunLoopEntry = (1UL << 0), //即将进入loop

kCFRunLoopBeforeTimers = (1UL << 1), //即将处理timer

kCFRunLoopBeforeSources = (1UL << 2), //即将处理source

kCFRunLoopBeforeWaiting = (1UL << 5), //即将进入休眠

kCFRunLoopAfterWaiting = (1UL << 6), //刚从休眠中唤醒

kCFRunLoopExit = (1UL << 7), //即将退出loop

kCFRunLoopAllActivities = 0x0FFFFFFFU //所有模式

};

现在我们来试一试,怎么去监听RunLoop的状态,是这样,RunLoop的监听模式没有OC的代码,我们可以用C语言代码来实现,如下:

从执行的结果来看,确实是这么多,点击事件是在source0执行,所以看log日志也是很清楚,

接下来我们看一下定时器唤醒RunLoop.我们知道kCFRunLoopBeforeWaiting是休眠睡觉,而kCFRunLoopAfterWaiting是唤醒休眠,我们看一下定时器是不是唤醒休眠,请看下面的代码:

从输出结果来看,确实是唤醒休眠.执行block

证明模式切换会退出RunLoop,再重新进入RunLoop

由上面的监听,我们是很容易可以证明这个结果吧?我们看一下代码,这次用上面说的另一种创建observe的方法,请看下图:随便创建一个可以滚动的view,比如我创建的Scrollerview.

当在滚动的时候,我们明显可以看到2种模式在切换,而且RunLoop也是需要退出重新进入才会切换到新的模式.

深入理解RunLoop的执行流程

网上的答案很多,这次我们从源码解析,一步一步的查看RunLoop的执行流程到底是怎么样的:因为源码比较抽象,是纯c语言的,不像我们之前的有c++源码比较好懂一点,那我们怎么找runloop开始的函数呢?很容易,我们知道点击也是通过runloop来处理的,那我们直接看点击事件的函数调用栈就知道入口了,请看下图:

从上面的代码可以很清楚的看出来是调用了CFRunLoopRunSpecific这个函数.那我们就去源码搜索这段代码很容易就搜索到.请看下面:

一看上面的源码,我们发现执行了非常多,你看绿色里面有锁,有多线程等等,所以我们没有必要研究得很透彻,浪费时间也没有意义,我们只要把大致流程捋顺了就行了,所以我们只要看关键代码,我只展示我们要看的关键代码如下:

接下来我们就去看__CFRunLoopRun源码里面到底执行了哪些操作,接下来的源码是我精简了的,大家可以参照源码看一下,因为里面东西非常多,我们没有必要全部了解,只要知道它的执行流程即可.请看下图:

如果条件不成立,就会设置返回值,到时候直接退出RunLoop,上面的流程相信我备注的已经非常清楚,对照一下源码看一下,你会印象更加深刻.下面我们用文字总结一下流程如下:

再放一个文字版的:

这个和源码基本一模一样的流程,可以参照一下,源码还是比较抽象的

接下来再看一个知识点.

__CFRunLoopDoBlocks、__CFRunLoopDoObservers、__CFRunLoopDoTimers里面执行了什么

其中RunLoop做了这么几件大事中比如blocks,timers,observers,我们看下里面具体是执行了什么,继续看源码,请看下图,比如我们就看__CFRunLoopDoSources0:

其实最终处理的就是这个:

__CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE0_PERFORM_FUNCTION__

我们再看下之前的一个截图

它上面两个处理的函数是一摸一样,也进一步的证明了,触摸事件是source0在处理.

定时器也是一样的道理,大家可以自己尝试一下.

理解线程休眠具体是什么意思?

RunLoop的线程休眠是真的休眠,它是不会占用任何cpu的资源,完全休息.它和white(1)这种还是有本质的区别,white(1)它是一直在执行,转成汇编会有几条指令,一直在执行,一直占用cpu资源,比如我们想做优化,那RunLoop的这种休眠模式是不是更节约cpu资源,说白了更省电些.就是如下源码的位置:

就是执行到当前代码,就不会往下走了,不会接着执行下面的代码,就会堵在这里,一旦别人唤醒它了,它才会接着往下执行.我们可能奇怪它是怎么做到的这种休眠?

我们看一下里面具体是怎么实现的,其实里面是执行了非常内核的函数叫做:mach_msg,我们可以看下

其实IPA可以分为内核层面的IPA:它是非常非常底层的,是操作系统层面的,它可以让线程休眠,也是真的休眠,不占用任何cpu资源,一般是不开放给我们程序员使用的,因为是比较内核的,给程序员使用危险也比较大,而应用层面的IPA,都是网络请求什么,页面什么.

所以mach_msg,我们面试的时候可以答出这个函数.

RunLoop休眠实现的原理

就是用户态和内核态的切换,用户态发消息,内核态休眠,再被唤醒,用户态处理消息.

所以如果面试官问:RunLoop里面线程阻塞是怎么样的?我们千万不能答,里面是个死循环.就是上面刚刚说的那些.

RunLoop与NSTimer的故事

相信我们在开发中遇到的次数是非常的多,这里稍微提一下.

比如我们常见的mode模式是有2种

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

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

我们在把Timer添加到runloop的时候,直接传入通用模式即可NSRunLoopCommonModes即可.

主要说一下它是怎么个原因.

我们看一下上个博客说的RunLoop的结构:

我们可以理解为传入NSRunLoopCommonModes,就是把这2种模式,放入_commonModes里面,也就是timer可以_commonModes数组中的模式下进行工作.注意NSRunLoopCommonModes这个不是一种模式哈.

而_commonModeItems里面存放的都是可以在_commonModes模式下工作的,比如刚刚的timer.

接下来我会继续介绍'线程保活'知识点.

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

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

推荐阅读更多精彩内容