美文网首页
RunLoop浅析

RunLoop浅析

作者: woniu | 来源:发表于2018-03-30 11:01 被阅读22次

    一、什么是RunLoop

    a、RunLoop实质上是一个死循环,保证程序持续运行,只有程序退出的时候才会结束。如下,在main.m文件中:

    #import <UIKit/UIKit.h>
    #import "AppDelegate.h"
    //开启主线程,同时默认开启主线程的RunLoop。
    int main(int argc, char * argv[]) {
        @autoreleasepool {
            return UIApplicationMain(argc, argv, nil, NSStringFromClass([AppDelegate class]));
        }
    }
    

    二、RunLoop使用原理和注意点

    a、一个RunLoop包含若干个Mode,每个Mode又包含若干个Source、Observer、Timer
    b、每次RunLoop启动,只能指定一个Mode,这个Mode被称为CurrentMode
    c、如果需要切换Mode,只能退出Loop,再重新指定一个Mode进入, 以使不同组之间的Source、Observer、Timer互不受影响

    三、RunLoop和线程的关系

    a、RunLoop与线程一一对应,且是管理线程的。
    b、RunLoop在主线程默认开启,在子线程中是懒加载。线程执行完毕之后进入休眠状态,有任务就会被唤醒。
    c、RunLoop在第一次获取时被创建,在线程结束时被销毁。
    d、对于子线程中的定时器,由于RunLoop是懒加载,只有我们使用的时候才会创建,所以要确保子线程的RunLoop被创建,不然定时器不会回调。

    NSRunLoop *loop = [NSRunLoop currentRunLoop];
    [loop run];
    

    NSTimer和RunLoop的关系:
    a、在子线程中,要启动分线程的RunLoop,NSTimer才能执行。因为分线程的RunLoop是默认关闭的。

      NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(update) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    

    四、RunLoop常用的两种模式

    a、NSDefaultRunLoopMode,默认模式,主线程中的RunLoop默认是NSDefaultRunLoopMode
    b、UITrackingRunLoopMode,在滚动式图的情况下RunLoop处于此模式下。常见的场景为TableView、CollectionView、ScrollView的滑动对定时器的影响。
    场景分析:
    由于一个RunLoop不能同时使用两个RunLoopMode,所以当视图滚动的时候,RunLoop从默认模式的NSDefaultRunLoopMode跳转到UITrackingRunLoopMode。由于定时器还是NSDefaultRunLoopMode模式,所以会停止。我们只要把定时器的RunLoop的模式设定为NSRunLoopCommonModes(占位Mode)即可。

    五、常用的使用场景

    a、异步线程下下载图片,如果失败该怎么处理呢?
    在此异步线程中启动一个RunLoop重新发送网络请求,下载图片。
    b、需要执行一个耗时操作,该怎么处理?
    开启一个异步子线程,启动它的RunLoop来执行该耗时操作。
    c、在分线程中开启一个异步请求,会有什么问题?
    我们需要判断请求是否结束,如果没有结束,要保持线程一直启动,直道结束的时候自动关闭。

    //创建一个线程,调用NSTimer事件
    NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(update) object:nil];
        // 设置线程的优先级(0.0 - 1.0,1.0最高级)
        thread.threadPriority = 1;
        // 开启线程
        [thread start];
    
    - (void)update{
        NSLog(@"----------分线程线程的定时器启动:%@",[NSThread currentThread]);
        
        @autoreleasepool{
        NSTimer *timer = [NSTimer timerWithTimeInterval:1.f target:self selector:@selector(newThing) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
            
        //在分线程中如果不开启RunLoop,那么定时器是无法执行的
    //    NSRunLoop *loop = [NSRunLoop currentRunLoop];
    //    [loop addPort:[NSMachPort port] forMode:NSRunLoopCommonModes];
    //
    //    [loop run];
        }
    }
    
    未开启分线程RunLoop.png
    开启分线程RunLoop.png

    相关文章

      网友评论

          本文标题:RunLoop浅析

          本文链接:https://www.haomeiwen.com/subject/xlmbcftx.html