美文网首页
iOS-定时器功能的实现

iOS-定时器功能的实现

作者: 棒棒德 | 来源:发表于2020-01-21 11:01 被阅读0次

    方式一:NSTimer

    1.创建方法:

    1.1 //需手动加入RunLoop

    /*

    TimeInterval:执行之前等待的时间。比如设置成1.0,就代表1秒后执行方法

    target:需要执行方法的对象

    selector:需要执行的方法

    repeats:是否需要循环

    */

    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

    [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];

    1.2 //自动将 timer加入到当前线程的RunLoop中

    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

    1.3 //Block方法,iOS 10新出的API,使用这个两个方法,要考虑到兼容性问题

    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)interval repeats:(BOOL)repeats block:(void (^)(NSTimer *timer))block API_AVAILABLE(macosx(10.12), ios(10.0), watchos(3.0), tvos(10.0));

    1.4 暂停、开始定时器

    /** < 开始定时器 > */if(self.timer.isValid) { self.timer.fireDate = [NSDate date]; } /** < 暂停定时器 > */if(self.timer.isValid) { self.timer.fireDate = [NSDate distantFuture]; }

    1.5 销毁定时器

    [self.timer invalidate];

    self.timer = nil;

    1.6 解决循环引用

    (稍后记录下来)

    1.7 缺点

    --- 易造成循环引用

    ---NSTimer 的定时器是在 RunLoop 中实现的,由于RunLoop在处理各种任务,所以会造成计时器不够准确,有时候会相对慢一些

    方式二:CGD

    1.简单实现-dispatch_after -- 延时执行,只执行一次,执行完后,就不再执行,如果重复某个操作,需要加逻辑实现不断调用

    //延时执行dispatch_after(dispatch_time(DISPATCH_TIME_NOW,(int64_t)(2*NSEC_PER_SEC)),dispatch_get_main_queue(),^{NSLog(@"-------延时执行--------");});

    缺点:

    无法取消

    2.复杂方法

    2.1 创建

    @property (noatomic, strong) dispatch_source_t timer;

    //获取队列,这里获取全局队列(tips:可以单独创建一个队列跑定时器)

    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);

    //创建定时器(dispatch_source_t本质还是个OC对象)

    self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

    //start参数控制计时器第一次触发的时刻,延迟0s

    dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, 0 * NSEC_PER_SEC);

    //    dispatch_time_t start = dispatch_walltime(NULL, 0);

    //每隔1s执行一次

    uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);

    dispatch_source_set_timer(self.timer, start, interval, 0);

    dispatch_source_set_event_handler(self.timer, ^{

        //要执行的任务

    });

    //开始执行定时器

    dispatch_resume(self.timer);

    2.2 开始定时器

    dispatch_resume(self.timer);

    2.3 暂停定时器

    dispatch_suspend(self.timer);

    2.4 取消定时器

    dispatch_cancel(self.timer);

    self.timer = nil;

    2.5 优点

    精准

    方案三:performSelector

    - (void)performSelector:(SEL)aSelector withObject:(nullableid)anArgument afterDelay:(NSTimeInterval)delay;

    也是延时一次,跟 dispatch_after 类似,但是可以随时取消,内部实现其实也是开启了一个定时器

    优点:

    可取消

    方案四:CADisplayLink

    创建

    /**  < 创建CADisplayLink >  */    

    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(printSeconds)];   

     /**  < 设置每秒刷新一次 The default value is 60 >  */    

    self.displayLink.preferredFramesPerSecond = 1;   

     /**  < 注册到RunLoop中 NSDefaultRunLoopMode >  */   

     [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop]forMode:NSDefaultRunLoopMode];    

    /**  < 暂停定时器 Initial state isfalse>  */    

    self.displayLink.paused = YES;

    暂停self.displayLink.paused = YES;

    开始self.displayLink.paused = NO;

    销毁

    /**  < 销毁定时器 >  */    [self.displayLink invalidate];    self.displayLink = nil;复制代码

    最后CADisplayLink相比NSTimer来说,精度要高的多,如果有想更深入的了解可以查看官方文档或相关博客(CADisplayLink)介绍的很详细。

    参考链接:

    https://juejin.im/post/5a371c995188256970781316

    https://juejin.im/post/5b641fc46fb9a04fd16033e7

    https://www.jianshu.com/p/dd6bc5082ec7

    相关文章

      网友评论

          本文标题:iOS-定时器功能的实现

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