• NSTimer的精确度


    1、iOS中一般UI上面常用两种定时器 NSTimer和CADisplayLink,那么它们分别的精确度是如何呢?

      CADisplayLink 是用于帧刷新定时器,也就是和界面的刷新率保持一致,理想情况下FPS为60,并尽力保持60

      NSTimer是否可以比CADisplayLink更加精确呢,最精确能下面的间隔是多少呢?NSTimer和CADisplayLink都作为一种事件加入到NSRunloop的事件源中,

      NSRunloop不断循环,判断是否应该触发这一类事件,如下面所示,NSRunloop包涵下面这些不同的事件:

      

    typedef CF_OPTIONS(CFOptionFlags, CFRunLoopActivity) {
        kCFRunLoopEntry         = (1UL << 0), // 即将进入Loop
        kCFRunLoopBeforeTimers  = (1UL << 1), // 即将处理 Timer
        kCFRunLoopBeforeSources = (1UL << 2), // 即将处理 Source
        kCFRunLoopBeforeWaiting = (1UL << 5), // 即将进入休眠
        kCFRunLoopAfterWaiting  = (1UL << 6), // 刚从休眠中唤醒
        kCFRunLoopExit          = (1UL << 7), // 即将退出Loop
    };
    

      可以看出,如果想让CADisplayLink正常工作,NSRunloop至少每秒循环60次,也就是至多17ms,那么NSRunloop每秒最多循环多少次呢?

    2、NSRunloop每秒循环多少次

      通过注册一个观察者到主线程中,观察每一种事件执行的log,来看看NSRunloop的执行情况

      

    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
        // Override point for customization after application launch.
        
        CFRunLoopObserverRef observer = CFRunLoopObserverCreateWithHandler(NULL, (kCFRunLoopAllActivities), YES, 0, ^(CFRunLoopObserverRef observer, CFRunLoopActivity activity)
        {
            static unsigned long count = 0;
            
            if(activity & kCFRunLoopEntry)
            {
                NSLog(@"activity %lu: %@", ++count, @"kCFRunLoopEntry");
            }
            else if(activity & kCFRunLoopBeforeTimers)
            {
                NSLog(@"activity %lu: %@", ++count, @"kCFRunLoopBeforeTimers");
            }
            else if(activity & kCFRunLoopBeforeSources)
            {
                NSLog(@"activity %lu: %@", ++count, @"kCFRunLoopBeforeSources");
            }
            else if(activity & kCFRunLoopBeforeWaiting)
            {
                NSLog(@"activity %lu: %@", ++count, @"kCFRunLoopBeforeWaiting");
            }
            else if(activity & kCFRunLoopAfterWaiting)
            {
                NSLog(@"activity %lu: %@", ++count, @"kCFRunLoopAfterWaiting");
            }
            else if(activity & kCFRunLoopExit)
            {
                NSLog(@"activity %lu: %@", ++count, @"kCFRunLoopExit");
            }
        });
        CFRunLoopAddObserver(CFRunLoopGetMain(), observer, kCFRunLoopCommonModes);
        
        
        return YES;
    }
    

      这里打印出每一类的事件,同时需要加上两类定时器到主线程中

    - (void)viewDidLoad {
        [super viewDidLoad];
        // Do any additional setup after loading the view, typically from a nib.
        
       NSTimer *timer = [NSTimer timerWithTimeInterval:0.001 repeats:YES block:^(NSTimer * _Nonnull timer) {
          
           static int timerCount = 0;
           //do nothing
           NSLog(@"timer do nothing, timerCount = %d", timerCount++);
       }];
        
       [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        
        
        CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(update:)];
        [link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    
        
    }
    
    
    - (void)update:(id)sender
    {
        static int linkCount = 0;
        NSLog(@"link do nothing, linkCount = %d", linkCount++);
    }
    

      可以观察出每一类事件执行的情况,测试是在iphone5s, ios10.2的系统上

    输出:

    NSRunloop:

    2017-03-18 13:01:54.145100 NSTimerTest[1121:267663] activity 20: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.148893 NSTimerTest[1121:267663] activity 24: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.150659 NSTimerTest[1121:267663] activity 28: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.153758 NSTimerTest[1121:267663] activity 32: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.155796 NSTimerTest[1121:267663] activity 36: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.158515 NSTimerTest[1121:267663] activity 40: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.160481 NSTimerTest[1121:267663] activity 44: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.162514 NSTimerTest[1121:267663] activity 48: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.165265 NSTimerTest[1121:267663] activity 52: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.169531 NSTimerTest[1121:267663] activity 56: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.229129 NSTimerTest[1121:267663] activity 74: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.232630 NSTimerTest[1121:267663] activity 78: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.233628 NSTimerTest[1121:267663] activity 82: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.235007 NSTimerTest[1121:267663] activity 86: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.236381 NSTimerTest[1121:267663] activity 90: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.237788 NSTimerTest[1121:267663] activity 94: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.238881 NSTimerTest[1121:267663] activity 98: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.239719 NSTimerTest[1121:267663] activity 102: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.240767 NSTimerTest[1121:267663] activity 106: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.241759 NSTimerTest[1121:267663] activity 110: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.242658 NSTimerTest[1121:267663] activity 114: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.243716 NSTimerTest[1121:267663] activity 118: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.244833 NSTimerTest[1121:267663] activity 122: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.245719 NSTimerTest[1121:267663] activity 126: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.247445 NSTimerTest[1121:267663] activity 130: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.248342 NSTimerTest[1121:267663] activity 134: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.250020 NSTimerTest[1121:267663] activity 138: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.251359 NSTimerTest[1121:267663] activity 142: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.252876 NSTimerTest[1121:267663] activity 146: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.254850 NSTimerTest[1121:267663] activity 150: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.256126 NSTimerTest[1121:267663] activity 154: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.257336 NSTimerTest[1121:267663] activity 158: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.258301 NSTimerTest[1121:267663] activity 162: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.259885 NSTimerTest[1121:267663] activity 166: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.261638 NSTimerTest[1121:267663] activity 170: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.262796 NSTimerTest[1121:267663] activity 174: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.264645 NSTimerTest[1121:267663] activity 178: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.265702 NSTimerTest[1121:267663] activity 182: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.266818 NSTimerTest[1121:267663] activity 186: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.268355 NSTimerTest[1121:267663] activity 190: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.269167 NSTimerTest[1121:267663] activity 194: kCFRunLoopBeforeWaiting
    2017-03-18 13:01:54.269909 NSTimerTest[1121:267663] activity 198: kCFRunLoopBeforeWaiting
    

      NSTimer

    2017-03-18 13:01:54.127460 NSTimerTest[1121:267663] timer do nothing, timerCount = 0
    2017-03-18 13:01:54.135893 NSTimerTest[1121:267663] timer do nothing, timerCount = 1
    2017-03-18 13:01:54.140639 NSTimerTest[1121:267663] timer do nothing, timerCount = 2
    2017-03-18 13:01:54.142266 NSTimerTest[1121:267663] timer do nothing, timerCount = 3
    2017-03-18 13:01:54.143658 NSTimerTest[1121:267663] timer do nothing, timerCount = 4
    2017-03-18 13:01:54.147695 NSTimerTest[1121:267663] timer do nothing, timerCount = 5
    2017-03-18 13:01:54.151489 NSTimerTest[1121:267663] timer do nothing, timerCount = 6
    2017-03-18 13:01:54.154552 NSTimerTest[1121:267663] timer do nothing, timerCount = 7
    2017-03-18 13:01:54.156480 NSTimerTest[1121:267663] timer do nothing, timerCount = 8
    2017-03-18 13:01:54.159303 NSTimerTest[1121:267663] timer do nothing, timerCount = 9
    2017-03-18 13:01:54.161246 NSTimerTest[1121:267663] timer do nothing, timerCount = 10
    2017-03-18 13:01:54.163655 NSTimerTest[1121:267663] timer do nothing, timerCount = 11
    2017-03-18 13:01:54.170411 NSTimerTest[1121:267663] timer do nothing, timerCount = 12
    2017-03-18 13:01:54.226209 NSTimerTest[1121:267663] timer do nothing, timerCount = 13
    2017-03-18 13:01:54.228032 NSTimerTest[1121:267663] timer do nothing, timerCount = 14
    2017-03-18 13:01:54.231912 NSTimerTest[1121:267663] timer do nothing, timerCount = 15
    2017-03-18 13:01:54.234140 NSTimerTest[1121:267663] timer do nothing, timerCount = 16
    2017-03-18 13:01:54.235779 NSTimerTest[1121:267663] timer do nothing, timerCount = 17
    2017-03-18 13:01:54.236939 NSTimerTest[1121:267663] timer do nothing, timerCount = 18
    2017-03-18 13:01:54.238231 NSTimerTest[1121:267663] timer do nothing, timerCount = 19
    2017-03-18 13:01:54.239210 NSTimerTest[1121:267663] timer do nothing, timerCount = 20
    2017-03-18 13:01:54.240251 NSTimerTest[1121:267663] timer do nothing, timerCount = 21
    2017-03-18 13:01:54.241185 NSTimerTest[1121:267663] timer do nothing, timerCount = 22
    2017-03-18 13:01:54.242131 NSTimerTest[1121:267663] timer do nothing, timerCount = 23
    2017-03-18 13:01:54.243136 NSTimerTest[1121:267663] timer do nothing, timerCount = 24
    2017-03-18 13:01:54.244139 NSTimerTest[1121:267663] timer do nothing, timerCount = 25
    2017-03-18 13:01:54.245170 NSTimerTest[1121:267663] timer do nothing, timerCount = 26
    2017-03-18 13:01:54.246129 NSTimerTest[1121:267663] timer do nothing, timerCount = 27
    2017-03-18 13:01:54.248936 NSTimerTest[1121:267663] timer do nothing, timerCount = 28
    2017-03-18 13:01:54.250729 NSTimerTest[1121:267663] timer do nothing, timerCount = 29
    2017-03-18 13:01:54.252273 NSTimerTest[1121:267663] timer do nothing, timerCount = 30
    2017-03-18 13:01:54.253343 NSTimerTest[1121:267663] timer do nothing, timerCount = 31
    2017-03-18 13:01:54.255634 NSTimerTest[1121:267663] timer do nothing, timerCount = 32
    2017-03-18 13:01:54.256494 NSTimerTest[1121:267663] timer do nothing, timerCount = 33
    2017-03-18 13:01:54.257829 NSTimerTest[1121:267663] timer do nothing, timerCount = 34
    2017-03-18 13:01:54.259261 NSTimerTest[1121:267663] timer do nothing, timerCount = 35
    2017-03-18 13:01:54.260290 NSTimerTest[1121:267663] timer do nothing, timerCount = 36
    2017-03-18 13:01:54.262144 NSTimerTest[1121:267663] timer do nothing, timerCount = 37
    2017-03-18 13:01:54.263531 NSTimerTest[1121:267663] timer do nothing, timerCount = 38
    2017-03-18 13:01:54.266225 NSTimerTest[1121:267663] timer do nothing, timerCount = 39
    2017-03-18 13:01:54.267656 NSTimerTest[1121:267663] timer do nothing, timerCount = 40
    2017-03-18 13:01:54.268629 NSTimerTest[1121:267663] timer do nothing, timerCount = 41
    2017-03-18 13:01:54.269641 NSTimerTest[1121:267663] timer do nothing, timerCount = 42
    2017-03-18 13:01:54.271133 NSTimerTest[1121:267663] timer do nothing, timerCount = 43
    2017-03-18 13:01:54.272366 NSTimerTest[1121:267663] timer do nothing, timerCount = 44
    2017-03-18 13:01:54.273213 NSTimerTest[1121:267663] timer do nothing, timerCount = 45
    2017-03-18 13:01:54.274115 NSTimerTest[1121:267663] timer do nothing, timerCount = 46
    2017-03-18 13:01:54.275425 NSTimerTest[1121:267663] timer do nothing, timerCount = 47
    2017-03-18 13:01:54.276400 NSTimerTest[1121:267663] timer do nothing, timerCount = 48
    2017-03-18 13:01:54.278951 NSTimerTest[1121:267663] timer do nothing, timerCount = 49
    2017-03-18 13:01:54.281740 NSTimerTest[1121:267663] timer do nothing, timerCount = 50
    2017-03-18 13:01:54.283120 NSTimerTest[1121:267663] timer do nothing, timerCount = 51
    2017-03-18 13:01:54.284362 NSTimerTest[1121:267663] timer do nothing, timerCount = 52
    

      CADisplayLink

    2017-03-18 13:01:54.138378 NSTimerTest[1121:267663] link do nothing, linkCount = 0
    2017-03-18 13:01:54.149657 NSTimerTest[1121:267663] link do nothing, linkCount = 1
    2017-03-18 13:01:54.166121 NSTimerTest[1121:267663] link do nothing, linkCount = 2
    2017-03-18 13:01:54.225401 NSTimerTest[1121:267663] link do nothing, linkCount = 3
    2017-03-18 13:01:54.233023 NSTimerTest[1121:267663] link do nothing, linkCount = 4
    2017-03-18 13:01:54.247794 NSTimerTest[1121:267663] link do nothing, linkCount = 5
    2017-03-18 13:01:54.265119 NSTimerTest[1121:267663] link do nothing, linkCount = 6
    2017-03-18 13:01:54.280689 NSTimerTest[1121:267663] link do nothing, linkCount = 7
    2017-03-18 13:01:54.298406 NSTimerTest[1121:267663] link do nothing, linkCount = 8
    2017-03-18 13:01:54.315036 NSTimerTest[1121:267663] link do nothing, linkCount = 9
    2017-03-18 13:01:54.331416 NSTimerTest[1121:267663] link do nothing, linkCount = 10
    2017-03-18 13:01:54.346888 NSTimerTest[1121:267663] link do nothing, linkCount = 11
    2017-03-18 13:01:54.363696 NSTimerTest[1121:267663] link do nothing, linkCount = 12
    2017-03-18 13:01:54.380435 NSTimerTest[1121:267663] link do nothing, linkCount = 13
    2017-03-18 13:01:54.398125 NSTimerTest[1121:267663] link do nothing, linkCount = 14
    2017-03-18 13:01:54.414091 NSTimerTest[1121:267663] link do nothing, linkCount = 15
    2017-03-18 13:01:54.430187 NSTimerTest[1121:267663] link do nothing, linkCount = 16
    2017-03-18 13:01:54.447019 NSTimerTest[1121:267663] link do nothing, linkCount = 17
    2017-03-18 13:01:54.463854 NSTimerTest[1121:267663] link do nothing, linkCount = 18
    2017-03-18 13:01:54.480343 NSTimerTest[1121:267663] link do nothing, linkCount = 19
    2017-03-18 13:01:54.513566 NSTimerTest[1121:267663] link do nothing, linkCount = 21
    2017-03-18 13:01:54.530110 NSTimerTest[1121:267663] link do nothing, linkCount = 22
    2017-03-18 13:01:54.547502 NSTimerTest[1121:267663] link do nothing, linkCount = 23
    2017-03-18 13:01:54.565346 NSTimerTest[1121:267663] link do nothing, linkCount = 24
    2017-03-18 13:01:54.580107 NSTimerTest[1121:267663] link do nothing, linkCount = 25
    2017-03-18 13:01:54.598014 NSTimerTest[1121:267663] link do nothing, linkCount = 26
    2017-03-18 13:01:54.629988 NSTimerTest[1121:267663] link do nothing, linkCount = 28
    2017-03-18 13:01:54.646657 NSTimerTest[1121:267663] link do nothing, linkCount = 29
    2017-03-18 13:01:54.663800 NSTimerTest[1121:267663] link do nothing, linkCount = 30
    2017-03-18 13:01:54.680001 NSTimerTest[1121:267663] link do nothing, linkCount = 31
    2017-03-18 13:01:54.697108 NSTimerTest[1121:267663] link do nothing, linkCount = 32
    2017-03-18 13:01:54.713726 NSTimerTest[1121:267663] link do nothing, linkCount = 33
    2017-03-18 13:01:54.729956 NSTimerTest[1121:267663] link do nothing, linkCount = 34
    2017-03-18 13:01:54.746658 NSTimerTest[1121:267663] link do nothing, linkCount = 35
    2017-03-18 13:01:54.763778 NSTimerTest[1121:267663] link do nothing, linkCount = 36
    2017-03-18 13:01:54.779953 NSTimerTest[1121:267663] link do nothing, linkCount = 37
    2017-03-18 13:01:54.796732 NSTimerTest[1121:267663] link do nothing, linkCount = 38
    2017-03-18 13:01:54.813729 NSTimerTest[1121:267663] link do nothing, linkCount = 39
    2017-03-18 13:01:54.829980 NSTimerTest[1121:267663] link do nothing, linkCount = 40
    2017-03-18 13:01:54.846751 NSTimerTest[1121:267663] link do nothing, linkCount = 41
    2017-03-18 13:01:54.863757 NSTimerTest[1121:267663] link do nothing, linkCount = 42
    2017-03-18 13:01:54.879957 NSTimerTest[1121:267663] link do nothing, linkCount = 43
    2017-03-18 13:01:54.896619 NSTimerTest[1121:267663] link do nothing, linkCount = 44
    2017-03-18 13:01:54.913648 NSTimerTest[1121:267663] link do nothing, linkCount = 45
    2017-03-18 13:01:54.930006 NSTimerTest[1121:267663] link do nothing, linkCount = 46
    2017-03-18 13:01:54.946953 NSTimerTest[1121:267663] link do nothing, linkCount = 47
    2017-03-18 13:01:54.963751 NSTimerTest[1121:267663] link do nothing, linkCount = 48
    2017-03-18 13:01:54.980065 NSTimerTest[1121:267663] link do nothing, linkCount = 49
    

      

    3、总结

      可以看出来,CADisplayLink“尽量”保证17ms执行一次,主要看NSRunloop中有没有执行其它事件时被阻塞

      NSTimer的触发周期最小可以和NSRunloop的循环保持一致,也就是由NSRunloop的执行周期决定,大概2~3ms

      因此这也是NSTimer也是不精确的原因

    代码:https://github.com/liqiushui/NSRunloop

  • 相关阅读:
    代码:城市名称的联想下拉框。可按拼音搜索、按汉字搜索,是一种很简单的实现方式
    代码:拖拽
    插件:zTree
    代码:遍历
    学习笔记:Stage.js(又叫Cut.js)——2D canvas 开发库,游戏方面的
    前端模块化、构建工具
    二级联动下拉菜单
    thinkphp的目录结构设计经验总结
    tp 路径表示
    liunx 根目录介绍
  • 原文地址:https://www.cnblogs.com/doudouyoutang/p/6573411.html
Copyright © 2020-2023  润新知