今天抽空复习了会Runloop,以前虽然特意的学过,但是工作中确比较少用到,所以利用今天这个机会把他记录下来。
Runloop意思就是运行循环,只有有了它,APP才能一直保持运行状态。Runloop的寄生于线程:一个线程只能有唯一对应的runloop;
Runloop内部就是一个死循环。但是他和一般的while(1);这种死循环还是有差别的。
Runloop的寄生于线程:一个线程只能有唯一对应的Runloop;
这就要讲到Runloop的几种模式。
目前接触到的几种Mode有:
/**
* Runloop的几种模式
*
* 1. NSDefaultRunLoopMode
* 默认模式中几乎包含了所有输入源(NSConnection除外),一般情况下应使用此模式。
*
* 2. NSRunLoopCommonModes
* 这是一个伪模式,其为一组run loop mode的集合,将输入源加入此模式意味着在Common Modes中包含的所有模式下都可以处理。
* 包含NSDefaultRunLoopMode和UITrackingRunLoopMode
*
* 3. UITrackingRunLoopMode
* 在拖动loop或其他user interface tracking loops时处于此种模式下,在此模式下会限制输入事件的处理。
*/
FOUNDATION_EXPORT NSString * const NSDefaultRunLoopMode;
FOUNDATION_EXPORT NSString * const NSRunLoopCommonModes NS_AVAILABLE(10_5, 2_0);
UIKIT_EXTERN NSString *const UITrackingRunLoopMode;
每个Mode中又包含若干个 Source/Observer/Timer
Source表示事件源,处理点击事件和一些系统事件。比如点击了一个按钮,系统会在添加一个点击事件到当前线程的Runloop里面的source中,然后在Runloop的下次循环中就会执行。
Observer是用来监听Runloop的状态的,Runloop对应几种状态
/* Run Loop Observer Activities */
typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
kCFRunLoopEntry = (1UL << 0),
kCFRunLoopBeforeTimers = (1UL << 1),
kCFRunLoopBeforeSources = (1UL << 2),
kCFRunLoopBeforeWaiting = (1UL << 5),
kCFRunLoopAfterWaiting = (1UL << 6),
kCFRunLoopExit = (1UL << 7),
kCFRunLoopAllActivities = 0x0FFFFFFFU
};
每当状态发生改变就会通知observerTimer表示定时器,所以我们创建的NSTimer要添加到Runloop中才能有效。
注意:如果Runloop中 Source/Observer/Timer 这三者都为空,Runloop会自动退出。
Runloop使用:
前面讲到Runloop是寄生于线程的,主线程因为Runloop才保证能一直运行下去,那么我们可以试着创建一个子线程,子线程默认执行完就退出了,那么我们可以给他添加Runloop,让他保持不死,等待着我们给他添加一些新的任务。事实上SDWebImage框架就是这么做的。创建一个专门用于图片下载的线程。当有图片需要下载的时候就添加任务到这个线程中。我们也可以创建一条专门服务于自己的线程,如一直在子线程监听用户操作,遍历Document文件夹等等。