Runloop

作者: 7d3fadbb4407 | 来源:发表于2018-01-29 11:53 被阅读7次

    Runloop的运用场景

    定时器NSTimer

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    

    这样写会有个问题,当屏幕有触摸事件时,该timer会卡住。什么原因?是线程卡住吗?其实不然,这就要说到另外一种模式:UITrackingRunLoopMode。看下图:


    Runloop

    默认模式:NSDefaultRunLoopMode
    UI模式:UITrackingRunLoopMode

    当UI模式没有被触发时,默认模式中的Timer会被执行。但当UI模式有事件,会优先触发该模式下的Source,用户体验高于一切。知道原因,那么好办,将Timer添加到UI模式下即可。

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode];
    

    但是,会出现另外一种情况,当UI没有事件触发时,timerAction不会每一秒执行。究其原因,UITrackingRunLoopMode虽然优先级高,但只能被触摸事件触发。那么我们可以这样写:

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode: NSDefaultRunLoopMode];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode: UITrackingRunLoopMode];
    

    确实,该代码不管UI有没有事件,timerAction都会每秒钟被调用。但怎么都觉得该代码有点奇怪,其实另一种mode可以包含该两种模式。即

    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];
    [[NSRunLoop mainRunLoop] addTimer:timer forMode: NSRunLoopCommonModes];
    

    这里顺便列一下NSRunloopMode

    1. NSRunLoopCommonModes          // 占位模式,包含UITrackingRunLoopMode、NSDefaultRunLoopMode,至于有没有其他模式,未知
    2. NSDefaultRunLoopMode          // 默认模式
    3. NSEventTrackingRunLoopMode    // 基本不使用
    4. NSModalPanelRunLoopMode       // 基本不使用
    5. UITrackingRunLoopMode         // UI模式
    

    该文章为笔记记录,如有朋友看到,且发现不妥之处,欢迎留言指正。

    相关文章

      网友评论

          本文标题:Runloop

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