NSRunLoop

一、NSRunLoop 介绍

NSRunLoop 顾名思义就是运行循环,这种循环用来处理理诸如鼠标和键盘事件之类的源的输入和 NSTimer 事件。
也即接受 input source 和 timer source 事件,交给线程处理。

二、NSRunLoop 和线程的关系

每个NSThread对象(包括应用程序的主线程)都有一个根据需要自动为其创建的NSRunLoop对象。
我们并不能自己创建 Runloop 对象,但是可以获取到系统提供的 Runloop 对象。
获取线程的运行循环,可以使用类方法 currentRunLoop 或者 mainRunLoop。
子线程的运行循环需要手动开启 [[NSRunLoop currentRunLoop] run]
子线程的 runloop 会随着线程的关闭而关闭,mainRunLoop 直到程序结束才会关闭。

三、NSRunLoop 工作模式

NSRunLoop 有四种工作模式分别为:
NSDefaultRunLoopMode
NSConnectionReplyMode
NSModalPanelRunLoopMode
NSEventTrackingRunLoopMode
NSRunLoopCommonModes
其中 iOS 公开的有 NSDefaultRunLoopMode 和 NSRunLoopCommonModes。
NSRunLoopCommonModes 实际上是一个 Mode 的集合,默认包括 NSDefaultRunLoopMode 和 NSEventTrackingRunLoopMode。

四、NSRunLoop 使用场景

滑动 ScrollView 时,定时器失效。
通常定时器默认以 NSDefaultRunLoopMode 添加到主线程中,而 ScrollView 在用户滑动时,主线程 RunLoop 会转到 UITrackingRunLoopMode,这个时候, Timer 就不会运行。

解决方案一:定时器以 NSRunLoopCommonModes 添加到线程中
self.activationDelayTimer = [NSTimer
                             timerWithTimeInterval:self.activationDelay target:self selector:@selector(activationDelayTimerFired) userInfo:nil repeats:NO];
[[NSRunLoop mainRunLoop] addTimer:self.activationDelayTimer forMode:NSRunLoopCommonModes];
解决方案二:定时器运行在专门的子线程中。
dispatch_async(dispatch_get_global_queue(0, 0), ^{
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(timerAcion:) userInfo:nil repeats:YES];
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    [[NSRunLoop currentRunLoop] run];
});
posted @ 2021-01-16 12:13  ebamboo  阅读(233)  评论(0)    收藏  举报