FPS的测量
对于FPS的测量,就是使用CADisplayLink计算某个时间段内某个方法的调用次数:
FPS = 调用次数 / 时间
1 2 3 4 5 6 7 8
   | #import <UIKit/UIKit.h>
  @interface FPSMeasurer : NSObject + (FPSMeasurer *)measurer; @property (nonatomic, getter=isPaused) BOOL paused; @property (nonatomic, assign) NSTimeInterval reportInterval; @property (nonatomic, copy) void (^reportBlock)(double fps, UIColor *fpsColor); @end
 
  | 
 
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81
   | #import "FPSMeasurer.h" #import <QuartzCore/QuartzCore.h>
  @interface FPSMeasurer () @property (nonatomic, strong) CADisplayLink *displayLink; @property (nonatomic, assign) NSTimeInterval lastTimestamp; @property (nonatomic, assign) NSUInteger frames; @end
  @implementation FPSMeasurer
  static FPSMeasurer *measurer = nil;
  + (FPSMeasurer *)measurer {     static dispatch_once_t onceToken;     dispatch_once(&onceToken, ^{         measurer = [[super allocWithZone:NULL] init];     });     return measurer; }
  + (instancetype)allocWithZone:(struct _NSZone *)zone {     return [FPSMeasurer measurer]; }
  - (instancetype)init {     if (self = [super init]) {         _reportInterval = 1;                  _displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkSelector:)];         [_displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSRunLoopCommonModes];     }     return self; }
  - (void)displayLinkSelector:(CADisplayLink *)displayLink {     ++self.frames;     if (self.lastTimestamp < DBL_EPSILON) {         self.lastTimestamp = displayLink.timestamp;     } else {         NSTimeInterval time = displayLink.timestamp - self.lastTimestamp;         if (time >= self.reportInterval) {             self.lastTimestamp = displayLink.timestamp;             NSUInteger frames = self.frames;             self.frames = 0;             if (self.reportBlock) {                 double fps = frames / time;                 self.reportBlock(fps, [UIColor colorWithHue:fps / 180.0 saturation:1 brightness:1 alpha:1]);             }         }     } }
  - (void)setReportInterval:(NSTimeInterval)reportInterval {     dispatch_block_t block = ^{         if (_reportInterval != reportInterval) {             _reportInterval = MAX(reportInterval, 0.1);         }     };     if ([NSThread isMainThread]) {         block();     } else {         dispatch_sync(dispatch_get_main_queue(), block);     } }
  - (void)setPaused:(BOOL)paused {     dispatch_block_t block = ^{         if (_paused != paused) {             _paused = paused;             _displayLink.paused = paused;         }     };     if ([NSThread isMainThread]) {         block();     } else {         dispatch_sync(dispatch_get_main_queue(), block);     } }
  @end
 
  | 
 
FPS的色彩表示
在用颜色展现FPS的高低时,通常是红色表示低帧率;绿色表示高帧率;橙色、黄色、黄绿色,表示高低之间的帧率。
为了将帧率转化为相应的颜色,最简单的方式就是使用HSB或HSL色彩空间。
在这两个色彩空间中,H都是色相,它的取值范围是0°到360°的圆心角。0°与360°对应红色、60°对应黄色、120°对应绿色。
在将帧率转化为颜色时,只需要改变H即可。
在iOS中,苹果提供了HSB色彩空间所对应的方法,H、S、B取值被限制在[0, 1.0]区间内。
在iOS 10之后(含iOS 10),不会对H、S、B的取值进行限制,对于[0, 1]区间外的值,会使用扩展的色彩空间
因此,在将帧率转化为颜色时,H的值可以用FPS / 60.0 * 120.0 / 360.0进行计算,也就是FPS / 180.0,S、B固定为1.0(也可以固定为与1.0非常相近的值)。
[UIColor colorWithHue:FPS / 180.0 saturation:1 brightness:1 alpha:1]
由于HSL与HSB有一些区别,如果使用的是HSL,L需要取值0.5(也可以取与0.5非常相近的值)。