iOS底层day8 - RunLoop

2018-10-31  本文已影响0人  宁夏灼雪__

什么是RunLoop

运行循环,可以在程序运行中做一些事情(处理source、timer、observer),一个线程对应一个RunLoop,主线程默认开启RunLoop,子线程需要手动触发,我们一个iOS应用就是启动了RunLoop一直在循环(UIApplicationMain),所以程序才没有退出。

RunLoop应用

RunLoop的基本作用

RunLoop结构

我们先看图:


runloop结构

每个RunLoop里面会保留一个_pthread线程对象,一个RunLoop对应一个_pthread_currentMode为当前RunLoop的时运行模式,一个模式包含了_source0_source1_observers_timers,一个RunLoop同一个时间点只能运行一个模式currentMode

RunLoop运行逻辑

RunLoop运行逻辑

大致了解一下,RunLoop里面在循环处理Blocks、Timer、Source、Observer、GCD等操作,处理结束会进入休眠,唤醒又会继续处理操作

RunLoop在开发中的应用

处理NSTimer在滑时停止工作

因为RunLoop从静止状态切换到滑动状态的时候是切换Mode的,从NSDefaultRunLoopMode切换到UITrackingRunLoopMode,而定时器的处理是在NSDefaultRunLoopMode中,所以这里的解决方案是把定时器加入到NSRunLoopCommonModes

控制线程声明周期 (线程保活)

一个线程执行完他的事情后,线程就会销毁,而我们开发中有时候需要一个常驻线程,用于处理一些耗时的操作,而我们一直创建线程、销毁线程是比较消耗性能的一件事, 所以,我们必须在程序运行中保护好该线程,这里就需要使用到RunLoop
例子如下:

#import "ViewController.h"
#import "MJThread.h"
@interface ViewController ()
@property (nonatomic,assign)BOOL isStop;
@property (nonatomic,strong)MJThread *thread;
@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];
    __weak typeof(self)weakSelf = self;
    self.isStop = NO;
    self.thread = [[MJThread alloc] initWithBlock:^{
        NSLog(@"---begin---");
        [[NSRunLoop currentRunLoop] addPort:[[NSPort alloc] init] forMode:NSDefaultRunLoopMode];
        while (weakSelf && !weakSelf.isStop) {
            [[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
        }
        NSLog(@"---end---");
    }];
    [self.thread start];
    
}

- (IBAction)stop {
    if (!self.thread) return;
    [self performSelector:@selector(stopAction) onThread:self.thread withObject:nil waitUntilDone:YES];
}

- (void)stopAction {
    
    self.isStop = YES;
    CFRunLoopStop(CFRunLoopGetCurrent());
    self.thread = nil;
}

- (void)touchesBegan:(NSSet<UITouch *> *)touches withEvent:(UIEvent *)event
{
    // 执行
    if (!self.thread) return;
    [self performSelector:@selector(run) onThread:self.thread withObject:nil waitUntilDone:YES];
}

- (void)run {
    NSLog(@"------%s----%@---",__func__,[NSThread currentThread]);
}


@end

这里,我们启动一个线程,在线程中获取RunLoop,因为子线程的RunLoop默认是没有东西的,如果不往RunLoop里面添加东西的话,它就会了立刻结束,所以我们在这里添加一个NSPort对象,接下来我们进入一个While循环执行runMode,在我理解里,runMode方法类似RunLoop的一次循环,这里进入了休眠,而我们加入一个while循环,就可以实现我们手动控制它循环,只有当我们手动把标记换掉后,停止RunLoop,循环才会结束,线程就会销毁

上一篇下一篇

猜你喜欢

热点阅读