Runloop(-)

一、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,但当线程被创建后,执行完任务后线程已经进入消亡状态, 是无法再次开启, 更不能执行其他任务.(通过一个死循环,去操作,让这个线程不死)

你可能感兴趣的:(Runloop(-))