定时器NSTimer,CADisplayLink,dispatch_source_t

1、NSTimer特性

       timer实际触发事件的时间与runloop有关,如果此时的runloop在执行一个耗时运算,timer就会被延时触发。重复性的timer遇到这种情况,如果延迟超过一个周期,则会在延时结束后立即执行,并按照之前指定的周期继续执行。

        必须加入runloop,使用scheduledTimerWithTimeInterval创建的,会自动加入mainrunloop中NSDefaultRunloopMode中,如果使用其他方式创建,需要手动加入runloop

NSTimer*timer=[NSTimer timerWithTimeInterval:6 target:selfselector:@selector(timerAction)userInfo:nil repeats:YES];

[[NSRunLoop mainRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];

选择的mode是default的话,当滑动scrollView的时候,定时器是会停止的,你可以将mode设置为common


2.CADisplayLink特性

        CADisplayLink是一个以屏幕刷新率将特定的内容画到屏幕上的定时器。CADisplayLink以特定模式注册到runloop后,每当屏幕刷新显示内容结束,runloop就会向CADisplayLink指定的targret发送一次指定的selector消息,CADisplayLink类对应的selector就会调用一次。

        延迟iOS设备的屏幕刷新频率是固定的,CADisplayLink在正常的情况下,会再每次刷新结束调用,精度高,但是在调试的方法比较耗时时,超过了屏幕的刷新周期,就会导致跳过若干次回调机会,如果CPU过于繁忙,无法保证屏幕的60次/秒的刷新率,就会导致跳过若干次回调的机会,跳过次数取决于CPU的忙碌程度。

使用场景:

         从原理上可以看出,CADisplayLink适合做界面不停重绘,比如视频播放的时候,需要不断的获取下一帧用于界面渲染。


3.dispatch_source_t

与NSTimer和CADisplayLink相比,时间更准确,可以使用子线程,解决时间在主线程卡UI问题。

NSTimer会受到主线程的任务影响,CADisplayLink会受到CPU的负载影响,产生延误。

dispatch_source_t可以使用子线程,而且使用leeway参数指定可以接受的误差来降低资源的消耗。

dispatch_source可以重复使用,在我们一个页面上,需要多次用到时钟的话,可以将dispatch_source_t保存为属性,避免提前释放,然后循环挂起和恢复,就可以达到多次利用的效果。

dispatch_source_t的suspendhe和resume要依次进行,不然毁crash,而且必须现在resume的转台下才能执行cancel,不然也会crash.

@property (nonatomic, strong) dispatch_source_t timer;@property (nonatomic, assign) BOOL isSuspend; //定时器挂起状态isSuspend记录下挂起的状态,因为dispatch_source_t的suspend和resume要依次进行,不然会crash,而且必须在resume的状态下,才能执行cancel,不然也会crash!!isSuspend默认为YES,因为首次需要resume以启动定时器!- (dispatch_source_t)timer{ if (!_timer) { _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0,dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)); uint64_t interval = (uint64_t)(XYHeyMediaPhotoTimerInterval * NSEC_PER_SEC); dispatch_source_set_timer(_timer, DISPATCH_TIME_NOW, interval, 0); @weakify(self); dispatch_source_set_event_handler(_timer, ^{ dispatch_async(dispatch_get_main_queue(), ^{ @strongify(self); [self updatePhotoProgress]; }); }); } return _timer;}创建定时器,设置线程,启动时间,时间间隔,以及执行block,如果只执行一次,在block中调用cancel即可,我们这里默认为repeat!- (void)resumeTimer{ if (self.isSuspend) { dispatch_resume(self.timer); self.isSuspend = NO; }}在需要启动时钟的时候调用上述方法resumeTimer,只有在已挂起的状态才能执行成功,同理,挂起操作:- (void)suspendTimer{ if (!self.isSuspend) { dispatch_suspend(self.timer); self.isSuspend = YES; }}利用resumeTimer和suspendTimer,就可以重复利用该定时器了!!当我页面销毁的时候,要主动将定时器销毁掉:




你可能感兴趣的:(定时器NSTimer,CADisplayLink,dispatch_source_t)