风气网

iOS三种定时器的用法NSTimer、CADisplayLink、GCD

2024-09-20来自:本站整理

一、NSTimer
1.创建方法

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

target : 需要执行方法的对象。

selector : 需要执行的方法

repeats : 是否需要循环

2.释放方法

3.特点

存在延迟:不管是一次性的还是周期性的timer的实际触发事件的时间,都会与所加入的RunLoop和RunLoop Mode有关,如果此RunLoop正在执行一个连续性的运算,timer就会被延时出发。重复性的timer遇到这种情况,如果延迟超过了一个周期,则会在延时结束后立刻执行,并按照之前指定的周期继续执行。

必须加入Runloop:使用上面的创建方式,会自动把timer加入MainRunloop的NSDefaultRunLoopMode中。如果使用以下方式创建定时器,就必须手动加入Runloop:

二、CADisplayLink

什么是CADisplayLink

CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器。我们在应用中创建一个新的 CADisplayLink 对象,把它添加到一个runloop中,并给它提供一个 target 和selector 在屏幕刷新的时候调用。

一但 CADisplayLink 以特定的模式注册到runloop之后,每当屏幕需要刷新的时候,runloop就会调用CADisplayLink绑定的target上的selector,这时target可以读到 CADisplayLink 的每次调用的时间戳,用来准备下一帧显示需要的数据。例如一个视频应用使用时间戳来计算下一帧要显示的视频数据。在UI做动画的过程中,需要通过时间戳来计算UI对象在动画的下一帧要更新的大小等等。在添加进runloop的时候我们应该选用高一些的优先级,来保证动画的平滑。可以设想一下,我们在动画的过程中,runloop被添加进来了一个高优先级的任务,那么,下一次的调用就会被暂停转而先去执行高优先级的任务,然后在接着执行CADisplayLink的调用,从而造成动画过程的卡顿,使动画不流畅。

duration属性提供了每帧之间的时间,也就是屏幕每次刷新之间的的时间。我们可以使用这个时间来计算出下一帧要显示的UI的数值。但是 duration只是个大概的时间,如果CPU忙于其它计算,就没法保证以相同的频率执行屏幕的绘制操作,这样会跳过几次调用回调方法的机会。frameInterval属性是可读可写的NSInteger型值,标识间隔多少帧调用一次selector方法,默认值是1,即每帧都调用一次。如果每帧都调用一次的话,对于iOS设备来说那刷新频率就是60HZ也就是每秒60次,如果将 frameInterval 设为2 那么就会两帧调用一次,也就是变成了每秒刷新30次。我们通过pause属性开控制CADisplayLink的运行。当我们想结束一个CADisplayLink的时候,应该调用-(void)invalidate从runloop中删除并删除之前绑定的 targetselector
另外CADisplayLink 不能被继承。

1.创建方法

2.停止方法

当把CADisplayLink对象add到runloop中后,selector就能被周期性调用,类似于重复的NSTimer被启动了;执行invalidate操作时,CADisplayLink对象就会从runloop中移除,selector调用也随即停止,类似于NSTimer的invalidate方法。

3.特点:

屏幕刷新时调用:CADisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。CADisplayLink以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。所以通常情况下,按照iOS设备屏幕的刷新率60次/秒 延迟:iOS设备的屏幕刷新频率是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。但如果调用的方法比较耗时,超过了屏幕刷新周期,就会导致跳过若干次回调调用机会。 如果CPU过于繁忙,无法保证屏幕60次/秒的刷新率,就会导致跳过若干次调用回调方法的机会,跳过次数取决CPU的忙碌程度。 使用场景:从原理上可以看出,CADisplayLink适合做界面的不停重绘,比如视频播放的时候需要不停地获取下一帧用于界面渲染。4. 重要属性 frameInterval NSInteger类型的值,用来设置间隔多少帧调用一次selector方法,默认值是1,即每帧都调用一次。 duration readOnly的CFTimeInterval值,表示两次屏幕刷新之间的时间间隔。需要注意的是,该属性在target的selector被首次调用以后才会被赋值。selector的调用间隔时间计算方式是:调用间隔时间 = duration × frameInterval。

三、GCD

1.执行一次

swift版本:
DispatchSourceTimer
间隔定时器, 相当于repeats设置为true的Timer.
初始化

设置timer参数

示例: 获取验证码60s倒计时

注意事项: 下面两种操作会造成程序崩溃, 原因是: gcdTimer执行了suspend()操作后, 是不可以被直接释放的, 如果想关闭一个执行了suspend()操作的计时器, 需要先执行resume(), 再执行cancel(), 最后置nil.

CADisplayLink 与 NSTimer 有什么不同?

iOS设备的屏幕刷新频率是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。

NSTimer的精确度就显得低了点,比如NSTimer的触发时间到的时候,runloop如果在阻塞状态,触发时间就会推迟到下一个runloop周期。并且 NSTimer新增了tolerance属性,让用户可以设置可以容忍的触发的时间的延迟范围。

CADisplayLink使用场合相对专一,适合做UI的不停重绘,比如自定义动画引擎或者视频播放的渲染。NSTimer的使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。在UI相关的动画或者显示内容使用 CADisplayLink比起用NSTimer的好处就是我们不需要在格外关心屏幕的刷新频率了,因为它本身就是跟屏幕刷新同步的。给非UI对象添加动画效果我们知道动画效果就是一个属性的线性变化,比如UIView 动画的 EasyInEasyOut 。通过数值按照不同速率的变化我们能生成更接近真实世界的动画效果。我们也可以利用这个特性来使一些其他属性按照我们期望的曲线变化。比如当播放视频时关掉视频的声音我可以通过CADisplayLink来实现一个 EasyOut的渐出效果:先快速的降低音量,在慢慢的渐变到静音。

注意
通常来讲:iOS设备的刷新频率事60HZ也就是每秒60次。那么每一次刷新的时间就是1/60秒 大概16.7毫秒。当我们的frameInterval值为1
的时候我们需要保证的是 CADisplayLink调用的 target 的函数计算时间不应该大于 16.7否则就会出现严重的丢帧现象。在mac应用中我们使用的不是CADisplayLink而是 CVDisplayLink它是基于C接口的用起来配置有些麻烦但是用起来还是很简单的。



  • [童林支15964727297] - iOS三种定时器的用法NSTimer、CADisplayLink、GCD
    狄放购::必须加入Runloop:使用上面的创建方式,会自动把timer加入MainRunloop的NSDefaultRunLoopMode中。如果使用以下方式创建定时器,就必须手动加入Runloop:二、CADisplayLink 什么是CADisplayLink CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器。我们在应用中创建一个新的 CADisplayLink 对象...
  • [童林支15964727297] - swift中定时器(Timer) 的使用
    狄放购::1、由于ios是通过runLoop作为消息循环机制,主线程默认启动了runLoop,可是子线程没有默认的runLoop,因此在子线程启动runLoop即可。2、runLoop的mode问题 如果timer是add到defaultRunLoopMode中,会出现滑动中UITrackingRunLoopMode得不到调度,导致定时器失效。因为UITrackingRunLoopMode和KCFRunLoopDefaultMode都标记...
  • [童林支15964727297] - 在ios中怎么用定时器实现自动循环页面滑动
    狄放购::您好,具体思路是使用NSTimer的类方法 + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;使用这个类方法,可以让您在某个规定的时间内进行一个动作(target:(id)和selector:(SEL)),只要在...
  • [童林支15964727297] - IOS中关于NSTimer使用知多少
    狄放购::target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo; 来初始化一个 时间定时器 下面我写了一个很简单得例子 初始化一个定时器:-(void)initTimer { \/\/时间间隔 NSTimeInterval timeInterval =1.0 ;\/\/定时器 NSTimer showTimer = [NSTimer scheduled...
  • [童林支15964727297] - IOS中关于NSTimer使用知多少
    狄放购::2、timerWithTimeInterval这两个类方法创建出来的对象如果不用 addTimer: forMode方法手动加入主循环池中,将不会循环执行。并且如果不手动调用fair,则定时器不会启动。3、scheduledTimerWithTimeInterval这两个方法不需要手动调用fair,会自动执行,并且自动加入主循环池。4、init方法需要手动加入循环池,它...
  • [童林支15964727297] - iphone中如何创建一个定时器NSTimer
    狄放购::在.h文件中定义NSTimer变量:NSTimer *bubbleTimer;在.m文件中,用如下代码来启用定时器:\/\/先确保原来的Timer已经被销毁[self KillTimer];int delay = 5.0f;bubbleTimer = [NSTimer scheduledTimerWithTimeInterval:delaytarget:selfselector:@selector(BubbleTimer:)userInfo:nilrepeats:NO];repeats...
  • [童林支15964727297] - iOS 保证定时器进入后台依然运行
    狄放购::经验证 NSTimer , CADisplayLink , dispatch_source_t ,三个定时器,在进入到后台的时候,都会暂停,等到返回前台的时候,才会继续回调。看了一些博客说加上后台任务执行这句话可以保证 App 进入后台,定时器不会暂停,依然继续执行 经验证,后台执行任务也将暂停延迟,还是没办法解决 App 长时间进入后台...
  • [童林支15964727297] - 如何在ios编程中利用定时器实现在触发某事件10秒段内不可再做这件事事...
    狄放购::比如按下按钮 10秒后 才能继续点击。-(void) buttonPressed{ button.enabled = NO;[NSTimer scheduledTimerWithTimeInterval:10.0f target:self selector:@selector(buttonPress) userInfo:nil repeats:NO];} -(void) buttonPress{ button.enabled = YES;} ...
  • [童林支15964727297] - NSNotificatinonCenter iOS9以后不再需要移除观察者-备忘
    狄放购::NSPostWhenIdle:空闲发送通知 当运行循环处于等待或空闲状态时,发送通知,对于不重要的通知可以使用。NSPostASAP:尽快发送通知 当前运行循环迭代完成时,通知将会被发送,有点类似没有延迟的定时器。NSPostNow :同步发送通知 如果不使用合并通知 和postNotification:一样是同步通知。合并通知NSNotification...
  • [童林支15964727297] - iOS开发中的循环引用
    狄放购::在控制器(Controller)内,创建NSTimer实例作为其属性,由于定时器创建后,也会强引用该控制器对象,那么该控制器对象和定时器对象就相互循环引用了。要解决该循环引用,可以手动断开:如果是不重复的NSTimer对象,在回调方法里将其invalidate并置为nil即可。如果是重复的NSTimer对象,在适当位置将其...
  • 首页 热门
    返回顶部
    风记网