一、RunLoop基本作用:
1.保持程序的持续运行
2.处理App中的各种事件(比如触摸事件、定时器事件、Selector事件)
3.节省CPU资源,提高程序性能:该做事时做事,该休息时休息
二、iOS中有2套API来访问和使用RunLoop
1.Foundation------NSRunLoop
2.Core Foundation------CFRunLoopRef
NSRunLoop和CFRunLoopRef都代表着RunLoop对象
NSRunLoop是基于CFRunLoopRef的一层OC包装,所以要了解RunLoop内部结构,需要多研究CFRunLoopRef层面的API(Core Foundation层面)
三、线程与Runloop
Foundation
1.每条线程都有唯一的一个与之对应的Runloop对象
2.主线程的RunLoop默认是开启的,子线程需要主动开启.
3.RunLoop在第一次获取的时候被创建,在线程结束时销毁
四、获取RunLoop对象:
Foundation框架
[NSRunLoop currentRunLoop]; // 获得当前线程的RunLoop对象
[NSRunLoop mainRunLoop]; // 获得主线程的RunLoop对象
Core Foundation框架:
CFRunLoopGetCurrent(); // 获得当前线程的RunLoop对象
CFRunLoopGetMain(); // 获得主线程的RunLoop对象
五、RunLoop 相关类:
Core Foundation中关于RunLoop的5个类
CFRunLoopRef
CFRunLoopModeRef
CFRunLoopSourceRef
CFRunLoopTimerRef
CFRunLoopObserverRef
1.CFRunLoopModeRef:
CFRunLoopModeRef代表RunLoop的运行模式
一个 RunLoop 包含若干个 Mode,每个Mode又包含若干个Source/Timer/Observer
每次RunLoop启动时,只能指定其中一个 Mode,这个Mode被称作 CurrentMode
如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入
这样做主要是为了分隔开不同组的Source/Timer/Observer,让其互不影响
系统默认注册了5个Mode:
kCFRunLoopDefaultMode:App的默认Mode,通常主线程是在这个Mode下运行
UITrackingRunLoopMode:界面跟踪 Mode,用于 ScrollView 追踪触摸滑动,保证界面滑动时不受其他 Mode 影响
UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
GSEventReceiveRunLoopMode: 接受系统事件的内部 Mode,通常用不到
kCFRunLoopCommonModes: 这是一个占位用的Mode,不是一种真正的Mode
2.CFRunLoopSourceRef是事件源(输入源)
以前的分法
Port-Based Sources
Custom Input Sources
Cocoa Perform Selector Sources (self performSelector:<#(nonnull SEL)#> withObject:<#(nullable id)#> afterDelay:<#(NSTimeInterval)#> inModes:<#(nonnull NSArray*)#>) PerformSelector 就是Cocoa Perform Selector Sources.
现在的分法
Source0:非基于Port的
Source1:基于Port的 (Source1接收的事件最终是交给Source0去执行的)
3.CFRunLoopTimerRef是基于时间的触发器基本上说的就是NSTimer
注意:当设置了Runloop的模式后, 只能在对应的模式下,定时器才能起作用.
3.CFRunLoopObserverRef:
CFRunLoopObserverRef是观察者,能够监听RunLoop的状态改变
我们可以给runloop添加一些监听者,去做一些拦截操作。
六、RunLoop处理逻辑-官方版:
将输入源或定时源添加到RunLoop后, runloop就不的循环处理事件源的一些操作, 若没有事件源输入, runloop就进入休眠状态.
RunLoop处理逻辑-官方版
RunLoop处理逻辑-非官方版
在第一步之前,可以优化一下:判断Runloop模式中是否有事件源. 有就通知Observer ,即将计入Runloop,否则直接退出.
七、RunLoop应用:
1.NSTimer
2.ImageView显示:(加入有一个需要,在滚动view时,加载图片显示图片, 此时滚动View时,界面就会很卡,此时就可以运用RunLoop,延迟显示图片)
当滚动View时,Runloop处于UITrackingRunLoopMode 模式, 此时performSelector 这个scource 源是Runloop是不会执行的,虽然runloop可以有多种模式,但一次只能在一个模式下运行,执行退出当前模式,才能执行其他模式下的Scource.
3.常驻线程:(就是让一个线程不死, 一直等待响应某些事情, 获取希望能让一条线程,在后台去监测扫描用户的沙盒里的文件,这个时候需要一直使用线程等等).
注意:一定不能设置一个Strong 的成员属性来引用线程, 这是不允许的,虽然能保证线程不被dealloc,但当线程被创建后,执行完任务后线程已经进入消亡状态, 是无法再次开启, 更不能执行其他任务.(通过一个死循环,去操作,让这个线程不死)