FPS计算方法
FPS是Frame per second的缩写,即每秒的帧数.这一术语广泛的应用于计算机图形学,视频采集,游戏等。
CADisplayLink
CADisplayLink是一个能让我们以和屏幕刷新率相同的频率将内容画到屏幕上的定时器,创建一个新的 CADisplayLink 对象,把它添加到一个runloop中,并给它提供一个 target 和selector 在屏幕刷新的时候调用。一旦CADisplayLink已特定的模式注册到runloop滞后,每当屏幕需要刷新的时候,runloop就会调用绑定的target上的selector,这时target可以读到CADisplayLink的每次调用的时间戳。
_link = [CADisplayLink displayLinkWithTarget:[YYWeakProxy proxyWithTarget:self] selector:@selector(tick:)];
[_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];
- (void)tick:(CADisplayLink *)link {
if (_lastTime == ) {
_lastTime = link.timestamp;//timestamp(表示屏幕显示的上一帧的时间戳)
return;
} _count++;
NSTimeInterval delta = link.timestamp - _lastTime;
if (delta < ) return;//不足一秒
_lastTime = link.timestamp;
float fps = _count / delta;
_count = ; CGFloat progress = fps / 60.0;
UIColor *color = [UIColor colorWithHue:0.27 * (progress - 0.2) saturation: brightness:0.9 alpha:]; NSMutableAttributedString *text = [[NSMutableAttributedString alloc] initWithString:[NSString stringWithFormat:@"%d FPS",(int)round(fps)]];
[text setColor:color range:NSMakeRange(, text.length - )];
[text setColor:[UIColor whiteColor] range:NSMakeRange(text.length - , )];
text.font = _font;
[text setFont:_subFont range:NSMakeRange(text.length - , )]; self.attributedText = text;
}
代码参考:YYFPSLabel。
同功能代码推荐:RRFPSBar
问题:
1.[YYWeakProxy proxyWithTarget:self]如何避免循环引用。
eg.
[NSTimer timerWithTimeInterval:1.f target:self selector:@selector(tick:) userInfo:nil repeats:YES];
CADisplayLink *_link = [CADisplayLink displayLinkWithTarget:self selector:@selector(tick:)];
以上两种用法,都会对self强引用,此时 timer持有 self,self 也持有 timer,循环引用导致页面 dismiss 时,双方都无法释放,造成循环引用。
此时使用 __weak 也不能有效解决:
__weak typeof(self) weakSelf = self;
_link = [CADisplayLink displayLinkWithTarget:weakSelf selector:@selector(tick:)];
避免循环引用的问题详细讲解见另一篇文章
//关键字typeof说明
typeof的参数可以是两种形式:表达式或类型。
1,表达式的的例子:
如果将typeof用于表达式,则该表达式不会执行。只会得到该表达式的类型。
2,typeof构造中的类型名不能包含存储类说明符,如extern或static。不过允许包含类型限定符,如const或volatile。
例如,下列代码是无效的,因为它在typeof构造中声明了extern:
typeof(extern int) a;