YYFPSLabel的学习总结

一个可以让你的App同步屏幕刷新帧率的定时器对象。在初始化CADisplayLink的时候,提供一个target和selector,这样当屏幕刷新的时候,会根据target调用对应的selector方法,需要将这个定时器添加到run loop中去同步屏幕的刷新loop。

屏幕每秒的刷新次数在60次,所以selector方法会在一秒钟调用60次。

_link = [CADisplayLink displayLinkWithTarget:[YYWeakProxy proxyWithTarget:self] selector:@selector(tick:)];

[_link addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];

YYWeakProxy ???WTF?

作者的解释:
// 如果直接用 self 或者 weakSelf,都不能解决循环引用问题
// 将 timer 的 target 从 self ,变成了中间人 NSProxy
// timer 调用 target 的 selector 时,会被 NSProxy 内部转调用 self 的 selector

似乎是个中间人传话筒的意思,如它英文所说,Proxy。通过这个类来持有一个weak对象,能够避免循环引用的情况,比如在NSTimer、CADisplayLink的使用中。

- (id)forwardingTargetForSelector:(SEL)selector {
    return _target;
}

这一句是将YYWeakProxy不能处理的调用方法,转发给其持有的弱target来处理。也就是把上面的tick:方法交给self来处理,因为YYWeakProxy找不到tick:的方法。

至于下面的两个方法:

- (void)forwardInvocation:(NSInvocation *)invocation {
    void *null = NULL;
    [invocation setReturnValue:&null];
}

- (NSMethodSignature *)methodSignatureForSelector:(SEL)selector {
    return [NSObject instanceMethodSignatureForSelector:@selector(init)];
}

是当target被释放nil后,调用的保护代码,就是防止程序因为weak target释放后,直接crash掉。

YYFPSLabel的工作原理是,是利用CADisplayLink的与屏幕刷新同步调用的特性,计算一秒钟程序的FPS,并展示出来。

tick函数的核心代码并附上注释:

//首次调用tick函数时候的调用,记录起始时间
if (_lastTime == 0) {
    _lastTime = link.timestamp;
    return;
}

//记录tick函数调用次数
_count++;

//记录tick函数调用与起始时间的差值,如果小于一秒继续return,继续计数tick调用次数。
NSTimeInterval delta = link.timestamp - _lastTime;
if (delta < 1) return;

//大于一秒后,记录当前的时间戳为下次的起始时间。
_lastTime = link.timestamp;

//计算大约一秒的tick调用次数,也就是一秒钟屏幕的刷新次数,即FPS数。
float fps = _count / delta;

//重置计数变量
_count = 0;

总结

巧妙的利用CADisplayLink的特性,计算一秒钟因为屏幕刷新而调用的tick次数,算出一秒钟屏幕的刷新次数,进而算出FPS值。当然存在一定的不准确性,不过在辅助监测App性能方面,还是很有帮助的。

posted @ 2018-07-09 10:58  Mr轨迹  阅读(916)  评论(0编辑  收藏  举报