iOS-屏幕帧数

在看YYKit (https://github.com/ibireme/YYKit)代码时,发现项目里有一个查看当前屏幕帧数的小工具YYFPSLabel,能够实时查看当前的帧数。

简书作者yehot的gif

以下是YYFPSLabel重要代码:

  /**
     //创建一个CADisplayLink,用于获取帧数

     @param tick: 获取数据方法

     @return
     */
    _link = [CADisplayLink displayLinkWithTarget:[YYWeakProxy proxyWithTarget:self] selector:@selector(tick:)];
    
    //放到RunLoop中
    [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
 //获取帧数方法
- (void)tick:(CADisplayLink *)link {
    if (_lastTime == 0) {
        _lastTime = link.timestamp;
        return;
    }
    
    _count++;
    NSTimeInterval delta = link.timestamp - _lastTime;
    if (delta < 1) return;
    _lastTime = link.timestamp;
    
    //获取当前fps
    float fps = _count / delta;
    _count = 0;
    
    //UILabel富文本
    CGFloat progress = fps / 60.0;
    UIColor *color   = [UIColor colorWithHue:0.27 * (progress - 0.2) saturation:1 brightness:0.9 alpha:1];
    
    NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%d FPS",(int)round(fps)]];
    [text setColor:color range:NSMakeRange(0, text.length - 3)];
    [text setColor:[UIColor whiteColor] range:NSMakeRange(text.length - 3, 3)];
    text.font = _font;
    [text setFont:_subFont range:NSMakeRange(text.length - 4, 1)];
    self.attributedText = text;
}

详见代码

YYWeakProxy 这个类是用于保存一个弱的对象。它可以用来避免保留周期,如目标NSTimer或CADisplayLink。

为什么需要这么使用呢?
因为

CADisplayLink *_link = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];
[NSTimer timerWithTimeInterval:1.f target:self selector:@selector(tick:) userInfo:nil repeats:YES];

当使用以上代码的时候会导致循环引用,

__weak typeof(self) weakSelf = self;
_link = [CADisplayLink displayLinkWithTarget:weakSelf selector:@selector(tick:)];

使用weakself的时候,当界面退出之后计时器还在使用。

如何解决这个问题呢?
解决方法
1.使用YYWeakProxy提供的方法,释放计时器。
2.自己代码控制在合适的时候停止计时器。

总结

在学习YYFPSLabel中,学习了很多知识。

  • 使用NSTimer
    如果我们在界面上滚动一个scrollview,那么我们会发现在停止滚动前,控制台不会有任何输出,就好像scrollView在滚动的时候将timer暂停了一样。
    其实是runloop的mode在做怪。
    NSTimer与NSURLConnection默认运行在default mode下,这样当用户在拖动UITableView处于UITrackingRunLoopMode模式时,NSTimer不能fire,NSURLConnection的数据也无法处理。
    如果不使用YYWeakProxy,则需要将link放到runloop中。
    [_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
  • CADisplayLink
    这是一个定时器绑定到vsync显示,类似NSTimer。
    它总是在屏幕完成一次更新之前启动,它的接口设计的和NSTimer很类似,所以它实际上就是一个内置实现的替代,但是和timeInterval以秒为单位不同,CADisplayLink有一个整型的frameInterval属性,指定了间隔多少帧之后才执行。默认值是1,意味着每次屏幕更新之前都会执行一次。但是如果动画的代码执行起来超过了六十分之一秒,你可以指定frameInterval为2,就是说动画每隔一帧执行一次(一秒钟30帧)或者3,也就是一秒钟20次。

  • FPS

 The maximum fps in OSX/iOS Simulator is 60.00.
 The maximum fps on iPhone is 59.97.
 The maxmium fps on iPad is 60.0.
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

推荐阅读更多精彩内容

友情链接更多精彩内容