iOS-定时器功能的实现

2020-01-21  本文已影响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

上一篇下一篇

猜你喜欢

热点阅读