iOS中的定时器(CADisplayLink)

「这是我参与11月更文挑战的第21天,活动详情查看:2021最后一次更文挑战

关于 CADisplayLink

CADisplayLink 是用于同步屏幕刷新频率的计时器

  • CADisplayLink 是一个和屏幕刷新率一致的定时器。CADisplayLink 以特定模式注册到 runloop 后,每当屏幕显示内容刷新结束的时候,runloop 就会向 CADisplayLink 指定的 target 发送一次指定的 selector 消息,CADisplayLink 类对应的 selector 就会被调用一次。所以通常情况下,按照iOS设备屏幕的刷新率 60次/秒

  • iOS设备的屏幕刷新频率是固定的,CADisplayLink 在正常情况下会在每次刷新结束都被调用,精确度相当高。但如果调用的方法比较耗时,超过了屏幕刷新周期,就会导致跳过若干次回调调用机会

  • 如果CPU过于繁忙,无法保证屏幕 60次/秒 的刷新率,就会导致跳过若干次调用回调方法的机会,跳过次数取决CPU的忙碌程度


CADisplayLink 常用方法及属性

  • 创建方法

    当把 CADisplayLink 对象添加到 runloop 中后,并给它提供一个 targetselect 在屏幕刷新的时候调用

    CADisplayLink *link = [CADisplayLink displayLinkWithTarget:self selector:@selector(run)];
    
    [link addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
    复制代码
  • 停止方法

    执行 invalidate 操作时,CADisplayLink 对象就会从 runloop 中移除,selector 调用也随即停止,类似于 NSTimerinvalidate 方法

    [link invalidate];
    link = nil;
    复制代码
  • 重要属性

    • timestamp

      只读属性,这个属性返回上一次屏幕刷新的时间戳。如果视频播放的应用,可以通过时间戳来获取上一帧的具体时间,来计算下一帧

    • duration

      只读属性,这个属性返回每帧之间的时间,也就是屏幕每次刷新之间的时间间隔。需要注意的是,该属性在 targetselector 被首次调用以后才会被赋值。selector 的调用间隔时间计算方式是:调用间隔时间 = duration × frameInterval

    • frameInterval

      可读可写属性, NSInteger 类型的值,用来设置间隔多少帧调用一次 selector 方法,默认值是1,即每帧都调用一次。如果每帧都调用一次的话,对于iOS设备来说那刷新频率就是60HZ也就是每秒60次,如果将 frameInterval 设为2 那么就会两帧调用一次,也就是变成了每秒刷新30次

    • preferredFramesPerSecond

      可读可写属性,用来设置每秒刷新次数,默认值为屏幕最大帧率,目前是60。

      实际的屏幕帧率会和 preferredFramesPerSecond 有一定的出入,结果是由设置的值和屏幕最大帧率相互影响产生的。规则大概如下:

      如果屏幕最大帧率是60,实际帧率只能是15,20,30,60中的一种。如果设置大于60的值,屏幕实际帧率为60。如果设置的是26~35之间的值,实际帧率是30。如果设置为0,会使用最高帧率。

      常用于如果在特定帧率内无法提供对象的操作,可以通过降低帧率解决


CADisplayLink 的使用

由于跟屏幕刷新同步,非常适合UI的重复绘制,如:下载进度条,自定义动画设计,视频播放渲染等

这里示例一个简单的例子

- (void)viewDidLoad {
    [super viewDidLoad];
    
    CADisplayLink *disLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(test)];
    [disLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
    
    //每秒钟调用多次 默认60.
    disLink.preferredFramesPerSecond = 10;
}
- (void)test{ 
    NSLog(@"测试");
}
复制代码

Guess you like

Origin juejin.im/post/7032818807651434509