美文网首页
iOS定时器

iOS定时器

作者: 宙斯YY | 来源:发表于2018-05-24 10:08 被阅读10次

.iOS中三种定时器使用方式和区别

1.NSTimer

NSTimer启动方式有两种,第一种创建之后启动,第二种scheduled自启动,区别是第一种创建之后需要手动添加到NSRunLoop中才能生效,第二种是默认会添加到当前NSRunLoop中。

注:每个线程都有自己的NSRunLoop,只有主线程是默认开启的,子线程需要手动开启。NSTimer添加到开启的NSRunLoop中才会执行(见RunLoop和NSTimer)。

当前NSRunLoop很忙的时候会出现延迟不精准的现象,或者当前RunLoop模式不是timer源,则timer会停止运行。

a.添加到主线程循环的timer

NSTimer * timer=[NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"timer");
    }];
    [timer setFireDate:[NSDate distantFuture]];
    [[NSRunLoop mainRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];

b.默认添加到主线程循环的timer

NSTimer * timer=[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
        NSLog(@"timer");
    }];

开个子线程证明线程NSRunLoop的问题
如果把timer添加到NSRunLoop currentRunLoop中,而不启动该子线程runloop,那么定时器不会执行,必须手动启动子线程的runloop -->[[NSRunLoopcurrentRunLoop]runUntilDate:[NSDatedistantFuture]];
或者添加到主线程runloop中执行timer。
-->[[NSRunLoop mainRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];

dispatch_async(dispatch_get_global_queue(0, 0), ^{
        self->timer=[NSTimer timerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"timer");
        }];
        [self->timer setFireDate:[NSDate distantPast]];
        [[NSRunLoop currentRunLoop]addTimer:self->timer forMode:NSDefaultRunLoopMode];
        [[NSRunLoop currentRunLoop]runUntilDate:[NSDate distantFuture]];
    });
dispatch_async(dispatch_get_global_queue(0, 0), ^{
        self->timer=[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"timer");
        }];
        [[NSRunLoop currentRunLoop]runUntilDate:[NSDate distantFuture]];
    });

关于停止NSTimer的问题,停止的代码如下,目的是把timer从当前NSRunLoop中移除出去,并把timer指针置空,但是主线程NSTimer停止在主线程执行,子线程NSTimer停止要在子线程执行。

子线程NSTimer如果在主线程停止,那么"go on"不会执行。

[timer invalidate];
timer=nil;
NSOperationQueue * queue=[[NSOperationQueue alloc]init];
    NSBlockOperation * operation=[NSBlockOperation blockOperationWithBlock:^{
        self->timer=[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"timer");
        }];
        [[NSRunLoop currentRunLoop]runUntilDate:[NSDate distantFuture]];
        NSLog(@"go on");
    }];
    [queue addOperation:operation];

iOS10之前的方法

timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(test) userInfo:nil repeats:YES]

不手动调用[time invalidate];timer=nil;viewcontroller和timer造成循环引用,不会回收。

IOS10之后的方法

self->timer=[NSTimer scheduledTimerWithTimeInterval:1.0 repeats:YES block:^(NSTimer * _Nonnull timer) {
            NSLog(@"timer");
        }];

不手动调用[time invalidate];timer=nil;只要viewcontroller回收,timer也被回收。

2.CADisplayLink

基本使用方式,NSRunLoop的道理同NSTimer。

CADisplayLink最小刷新频率等同于屏幕1/60秒,只有CPU过忙,屏幕刷新频率小于1/60时才会出现不精确。

CADisplayLink * dislink=[CADisplayLink displayLinkWithTarget:self selector:@selector(dislink:)];
    dislink.preferredFramesPerSecond=1;
    [dislink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];

3.dispatch_source_t

不需要手动添加timer到runloop,只需要指定主线程队列还是子线程队列,注意事项就是timer要设置成为全局成员变量,被该对象引用,不然执行一次自动回收。

dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_global_queue(0, 0));
    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 1.0 * NSEC_PER_SEC);
    dispatch_source_set_event_handler(timer, ^{
        
    });
    dispatch_resume(timer);

区别:

简单来讲就是精准度CADisplayLink>dispatch_source>NSTimer

实现子线程timer使用dispatch_source更好

CADisplayLink使用场合相对专一,适合做UI的不停重绘,给非UI对象添加动画效果,比如当播放视频时关掉视频的声音我可以通过CADisplayLink来实现一个EasyOut的渐出效果:先快速的降低音量,在慢慢的渐变到静音。

dispatch_source可以使用子线程,解决跑在主线程上卡UI问题,但是如果使用主线程刷新UI,记得回调到主线程。dispatch_async(dispatch_main(), ^})

注:对于子线程定时器当然可以使用NSTimer通过启动子线程NSRunLoop和添加timer到该RunLoop上的方式,但是使用dispatch_source更方便。

相关文章

  • 无标题文章

    iOS NSTimer使用详解-开启、关闭、移除 定时器定时器详解ios定时器关闭定时器NSTimer 1、要使用...

  • iOS进阶-谈谈定时器

    目录 iOS提供定时器API 定时器开发中的坑 一、 iOS提供定时器API 二、定时器开发中的坑 2.1、必须办...

  • 定时器

    定时器 兼容ios

  • iOS中的定时器

    点击这里>> cocoaChina: iOS中的定时器 iOS中定时器有三种,分别是NSTimer、CADispl...

  • GCD定时器使用

    iOS中的常用定时器分为这几类: NSTimer CADisplayLink GCD定时器 选择GCD定时器原因:...

  • iOS:NSTimer的几种创建方式

    在iOS开发中,经常会用到定时器,iOS中常用的定时器有三种:NSTimer,GCD,CADisplayLink。...

  • iOS Timer

    iOS开发中定时器经常会用到,iOS中常用的定时器有三种,分别是NSTime,CADisplayLink和GCD。...

  • 每日笔记

    1、通过safari打开网页 2、iOS的几种定时器及区别 iOS的几种定时器及区别 3、long long类型 ...

  • iOS三大定时器

    iOS开发中定时器经常会用到,iOS中常用的定时器有三种,分别是NSTime,CADisplayLink和GCD。...

  • 定时器的使用介绍

    iOS中的定时器大致分为这几类: NSTimer CADisplayLink GCD定时器 (一)NSTimer ...

网友评论

      本文标题:iOS定时器

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