CADisplayLink的使用,显示屏幕帧数

在开发中我们经常会遇到使用计时器的情况,例如图片轮播,进度条的绘制等就是比较常见的应用场景.
常用的计时器有CADisplayLinkNSTimer,这篇文章来讲解下CADisplayLink的具体用法和注意事项

CADisplayLink概括

CADisplayLink是用于同步屏幕刷新频率的计时器,当屏幕刷新的时候就会调用对应的sel,所以不需要在设置间隔时间了.

CADisplayLink使用方法

初始化

通过 + (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel 初始化link对象

添加到runloop

如果想开启link需要把link加入到runloop中: - (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode.除非计时器被停止,否则每次屏幕刷新时,计时器的方法都会被触发.

每个计时器对象只能加入到一个runloop中,但是可以被添加到不同的模式中,当CADisplayLink被加入到runloop时,会被runloop隐式retain.如果想从所有的模式中移除计时器,需要执行-invalidate()方法.

从runloop中移除

移除计时器有两个方法:- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode- (void)invalidate.
我们来分析一下他们的异同

- removeFromRunLoop: forMode:会将接收者从给定的模式中移除,这个方法会对计时器进行隐式的release.在调用removeFromRunloop方法,需要做判断,如果当期计时器不在runloop的话,会出现野指针的crash.出现crash的原因是runloop多次调用了release方法,进行了over-release.

- (void)invalidate是从runloop所有模式中移除计时器,并取消计时器和target的关联关系.多次调用这个方法,不会出现crash.

 

 

通过对CADisplayLink的属性分析和讲解,来阐述计时器的扩展用法.

时间戳 timestamp

时间戳timestamp,这个属性用来返回上一次屏幕刷新的时间戳.计算帧数,可以通过 1/(当前的时间戳-记录上一次的时间戳)

预计的下一秒的时间戳 targetTimestamp

targetTimestamp,这个属性用来返回预计下一秒的时间戳.计算fps最好不要用这个属性,这是是预计值,与真实值有差异的.当然如果要求不严的话,也是可以用这个的,好处就是不需要记录上一次的值了,少了一个变量,

间隔时间 duration

duration,默认是1/60,用于提供屏幕最大刷新频率(maximumFramesPerSecond)下每一帧的时间间隔. 注意是最大的 , 不是实时的帧数.

暂停和开启 isPaused

isPaused设置为true时可以用于暂停通知.

修改帧率 preferredFramesPerSecond

修改帧率 : 如果在特定帧率内无法提供对象的操作,可以通过降低帧率解决.一个拥有持续稳定但是较慢帧率的应用要比跳帧的应用顺滑的多.
可以通过preferredFramesPerSecond来设置每秒刷新次数.preferredFramesPerSecond默认值为屏幕最大帧率(maximumFramesPerSecond),目前是60.
实际的屏幕帧率会和preferredFramesPerSecond有一定的出入,结果是由设置的值和屏幕最大帧率(maximumFramesPerSecond)相互影响产生的.规则大概如下:

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

 

frameInterva(iOS10弃用)

多少帧调用一次selector方法 , 默认是1, 设置为2的话就会在一个刷新简直中调用2次sel.我在ios12上设置已经无效了

 

需要注意CADisplayLink是不能被继承的.



链接:https://www.jianshu.com/p/a96a65093c3b

最后来个小demo :  https://www.jianshu.com/p/0eeb21244caa

计算屏幕帧数,此处写在了vc里,应该写在一个全局的地方,这样每个页面都可以看到帧数了


#import "ViewController.h"

@interface ViewController ()

@property (nonatomic,strong) CADisplayLink * link  ;

@end

@implementation ViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    CADisplayLink * link = [CADisplayLink displayLinkWithTarget:self selector:@selector(screenRefresh:)];
    [link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];
    link.preferredFramesPerSecond = 60;
    self.link = link;
}

- (void)screenRefresh:(CADisplayLink *)link {

    static CFTimeInterval lastTime = 0.0;
    static int count = 1;

    if (lastTime == 0) {
        lastTime = link.timestamp ;
        return;
    }

    if (link.timestamp - lastTime<=0.5) {
        count ++;
        return;
    }
    double  fps = count/(link.timestamp - lastTime);
    static UILabel *redLabel = nil;
    if (redLabel == nil) {
        redLabel = [[UILabel alloc] initWithFrame:CGRectMake(100, 100, 100, 30)];
        redLabel.backgroundColor = [UIColor redColor];
        redLabel.textAlignment = NSTextAlignmentCenter;
        redLabel.layer.zPosition = 1;
        [[[UIApplication sharedApplication] keyWindow] addSubview:redLabel];
    }

    redLabel.text = [NSString stringWithFormat:@"帧数:%d",(int)fps];
    if (fps<30) {
        NSLog(@"%@",redLabel.text);
    }
    NSLog(@"%lf %lf %lf %lf",fps,link.duration,link.timestamp,link.targetTimestamp);
    lastTime = link.timestamp ;
    count = 1;

}

@end

添加定时器

- (void)addLink {
        _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(rotate)];
        [_displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
 // 旋转动画
- (void)rotate {
    _bgImageView.transform = CGAffineTransformRotate(_bgImageView.transform, M_PI/240);
}

销毁定时器

- (void)viewWillDisappear:(BOOL)animated {
    [super viewWillDisappear:animated];
    if (_displayLink) {
        [_displayLink invalidate];
        _displayLink = nil;
    }
}

 

在扩充一个东西 , 实时显示app的使用内存大小和cpu使用率,这个到也可以通过xcode来看。

https://blog.csdn.net/u014600626/article/details/102755792

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值