收录:原文地址
获取更多资料
RunLoop简介
Run 表示运行,Loop 表示循环。结合在一起就是运行循环的意思。RunLoop就是在程序运行过程中循环做一些事情。主要应用于以下:
定时器(Timer)、PerformSelector
GCD Async Main Queue
事件响应、手势识别、界面刷新
网络请求
AutoreieasePool
没有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等等.
,iOS技术交流群: 711315161,大家一起交流学习。群内有许多技术大牛,高手如云,有任何问题,欢迎广大网友一起来交流,群内还不定期免费分享中高阶iOS学习视频资料和面试资料包~