1. 简介
CADisplayLink
是一个能让我们以和屏幕刷新率
相同的频率将内容画到屏幕上的定时器。
我们在应用中创建一个CADisplayLink
对象,把它添加到一个runloop
中,并给它提供一个target
和selector
在屏幕刷新的时候调用。一但CADisplayLink
以特定的模式注册到runloop
之后,每当屏幕需要刷新的时候,runloop
就会调用CADisplayLink
绑定的target
上的selector
,这时target
可以读到CADisplayLink
的每次调用的时间戳,用来准备下一帧显示需要的数据。
在添加进runloop
的时候我们应该选用高一些的优先级
,来保证动画的平滑。可以设想一下,我们在动画的过程中,runloop
被添加进来了一个高优先级的任务,那么,下一次的调用就会被暂停转而先去执行高优先级的任务,然后在接着执行CADisplayLink
的调用,从而造成动画过程的卡顿,使动画不流畅。
2. API
/*
需要注意 定时器对象创建后 并不会马上执行 需要添加到runloop中
*/
+ (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel;
//将当前定时器对象加入一个RunLoop中
- (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode;
//将当前定时器对象从一个RunLoop中移除 如果这个Runloop是定时器所注册的最后一个 移除后定时器将被释放
- (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSRunLoopMode)mode;
//将定时器失效掉 调用这个函数后 会将定时器从所有注册的Runloop中移除
- (void)invalidate;
//当前时间戳
@property(readonly, nonatomic) CFTimeInterval timestamp;
//距离上次执行所间隔的时间
@property(readonly, nonatomic) CFTimeInterval duration;
//预计下次执行的时间戳
@property(readonly, nonatomic) CFTimeInterval targetTimestamp;
//设置是否暂停
@property(getter=isPaused, nonatomic) BOOL paused;
//设置预期的每秒执行帧数 例如设置为1 则以每秒一次的速率执行
@property(nonatomic) NSInteger preferredFramesPerSecond CA_AVAILABLE_IOS_STARTING(10.0, 10.0, 3.0);
//同上
@property(nonatomic) NSInteger frameInterval
CA_AVAILABLE_BUT_DEPRECATED_IOS (3.1, 10.0, 9.0, 10.0, 2.0, 3.0, "use preferredFramesPerSecond");
3. 具体使用
可以用来监测FPS
(FPS = Frames Per Second 每秒渲染多少帧
)的值,通常情况下,屏幕会保持60hz/s
的刷新速度,每次刷新时会发出一个屏幕刷新信号,我们可以使用CADisplayLink
通过屏幕刷新机制来展示fps
值:
@interface ViewController ()
@property (nonatomic, assign) NSInteger count;
@property (nonatomic, assign) NSTimeInterval lastTime;
@end
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(displayLinkMethod:)];
[displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSRunLoopCommonModes];
}
- (void)displayLinkMethod:(CADisplayLink *)displayLink{
if(_lastTime == 0){
_lastTime = displayLink.timestamp;
return;;
}
_count++;
NSTimeInterval delta = displayLink.timestamp - _lastTime;
if(delta < 1) return;
_lastTime = displayLink.timestamp;
CGFloat fps = _count / delta;
_count = 0;
NSInteger intFps = (NSInteger)(fps + 0.5);
NSLog(@"%d",intFps);
}
网友评论