在看YYKit (https://github.com/ibireme/YYKit)代码时,发现项目里有一个查看当前屏幕帧数的小工具YYFPSLabel,能够实时查看当前的帧数。
以下是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.