NSRunLoop

作者: 放牧塞外 | 来源:发表于2018-05-18 00:39 被阅读0次

目的:

  1. 保证线程不退出
  2. 负责监听事件:触摸、时钟、网络

NSRunLoop模式:

NSDefaultRunLoopMode 默认模式
UITrackingRunLoopMode UI模式
NSRunLoopCommonModes UI和默认(组合模式,不能算是Runloop的一种模式)
UIInitializationRunLoopMode: 在刚启动 App 时第进入的第一个 Mode,启动完成后就不再使用
kCFRunLoopDefaultMode: App的默认 Mode,通常主线程是在这个 Mode 下运行的

注意:

  • UI模式优先级最高
  • UI模式只能被UI事件所唤醒
  • 在NSRunLoopCommonModes模式下,不可以调用sleep方法,会阻塞主线程

案例 一

界面上半部分有一个滚动的轮播图,下面部分有一个tableview,当tableview滚动的时候,轮播图卡主不动

  • 分析

    轮播图通过NSTimer控制滚动,运行在主线程

    [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
    

    NSTimer 创建后被系统加入到Runloop中,使用了NSDefaultRunLoopMode模式
    当tableview滚动时,UI线程也就是主线程在执行,
    就会执行 UITrackingRunLoopMode模式Runloop的方法,
    UI模式的优先级最高,就造成了NSTimer的阻塞,从而导致轮播图卡主不动

  • 解决方法:

     //创建NStimer  
     NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];  
    //加入到Runloop中  
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];  
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];  
    //或者  
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];  
    

案例 二

先来一段代码

- (void)viewDidLoad {
    [super viewDidLoad];
    NSThread *thread = [[NSThread alloc] initWithBlock:^{
        NSTimer *timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(timerMethod) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
       NSLog(@"来了!!!");
    }];
    [thread start];
}

- (void)timerMethod{
    NSLog(@"come here");
    [NSThread sleepForTimeInterval:1.0];
    static int a = 0;
    a++;
    NSLog(@"%d----%@",a,[NSThread currentThread]);
}

代码执行后输出

NSRunLoop[65121:4770362] 来了!!!
  • 分析

    有耗时操作,肯定会选择放在线程里执行
    首先 NSThread 线程内部一定会加入Runloop,但是子线程不会使用到UITrackingRunLoopMode模式。
    当代码执行到 NSLog(@"来了!!!"); 这个线程的Block已经执行完毕,会销毁内部创建的timer以及Runloop,
    所以- (void)timerMethod方法不会执行

    定义成属性保持住@property (nonatomic, strong) NSThread *thread;
    会发现并没有效果- (void)timerMethod仍然没有执行!!!
    Strong只能保持住OC对象,线程还是会释放,只是在堆内存中存放了一个NSThread的结构体,这时调用[_thread start]; 就会Crash。
    因为NSthread操作的子线程,这时的子线程已经释放。

  • 解决方案

    Runloop在第一次获取的时候,就被创建--类似懒加载
    Runloop创建之后,默认是不循环的,必须手动开启

    [[NSRunLoop currentRunLoop] addTimer:timer forMode: NSDefaultRunLoopMode];  
    [[NSRunLoop currentRunLoop] run]; 
    

相关文章

  • NSRunLoop作用

    NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执行和...

  • NSRunLoop

    NSRunLoop--NSRunLoop是IOS消息机制的处理模式,控制NSRunLoop里面线程的执行和休眠,在...

  • NSRunLoop 详解

    1.NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执...

  • NSRunLoop详解

    1.NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执...

  • 关于NSRunLoop和NSTimer的深入理解

    一、什么是NSRunLoop NSRunLoop是消息机制的处理模式。 NSRunLoop的作用在于有事情做的时候...

  • 【转】NSRunLoop详解

    1.NSRunLoop是IOS消息机制的处理模式 NSRunLoop的主要作用:控制NSRunLoop里面线程的执...

  • NSRunLoop

    一、什么是NSRunLoop NSRunLoop是消息机制的处理模式 NSRunLoop的作用在于有事情做的时候使...

  • NSRunLoop和NSTimer的理解

    一、什么是NSRunLoop NSRunLoop是消息机制的处理模式 NSRunLoop的作用在于有事情做的时候使...

  • NSRunLoop和NSTimer

    一、什么是NSRunLoop NSRunLoop是消息机制的处理模式 NSRunLoop的作用在于有事情做的时候使...

  • 关于NSRunLoop和NSTimer的深入理解

    文章转自刚刚在线 一、什么是NSRunLoop NSRunLoop是消息机制的处理模式 NSRunLoop的作用在...

网友评论

      本文标题:NSRunLoop

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