iOS-计时器

来源:互联网 发布:windows 卡在欢迎界面 编辑:程序博客网 时间:2024/05/21 14:53

在iOS开发中定时器的实现有三种方式:NSTimer、CADisplayLink、GCD

GCD:

//GCD-(void)GCDMethod{    timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());    //每2秒执行一次,误差在0.1秒以内    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 2.0f * NSEC_PER_SEC, 0.1 * NSEC_PER_SEC);    dispatch_source_set_event_handler(timer, ^{        NSLog(@"GCD");    });    dispatch_resume(timer);}

注意其中的timer变量实为类内的成员变量或者成员属性

{    dispatch_source_t timer;}

如果在类内定义局部变量,会在类完毕后销毁,起不到定时器的作用

CADisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。CADisplayLink以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息, CADisplayLink类对应的selector就会被调用一次。所以通常情况下,按照iOS设备屏幕的刷新率60次/秒

//CADisplayLink-(void)CADisplayLinkMethod{    CADisplayLink *displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(timerMethod)];    //NSInteger类型的值,用来设置间隔多少帧调用一次selector方法,默认值是1,即每帧都调用一次。(1秒=60帧)    [displayLink setFrameInterval:120]; //120 相当于2秒调用一次    [displayLink addToRunLoop:[NSRunLoop mainRunLoop] forMode:NSDefaultRunLoopMode];}-(void)timerMethod{    NSLog(@"CADisplayLink");}

延迟

iOS设备的屏幕刷新频率是固定的,CADisplayLink在正常情况下会在每次刷新结束都被调用,精确度相当高。但如果调用的方法比较耗时,超过了屏幕刷新周期,就会导致跳过若干次回调调用机会。
如果CPU过于繁忙,无法保证屏幕60次/秒的刷新率,就会导致跳过若干次调用回调方法的机会,跳过次数取决CPU的忙碌程度。
使用场景

从原理上可以看出,CADisplayLink适合做界面的不停重绘,比如视频播放的时候需要不停地获取下一帧用于界面渲染。

重要属性

frameInterval
NSInteger类型的值,用来设置间隔多少帧调用一次selector方法,默认值是1,即每帧都调用一次。

duration
readOnly的CFTimeInterval值,表示两次屏幕刷新之间的时间间隔。需要注意的是,该属性在target的selector被首次调用以后才会被赋值。selector的调用间隔时间计算方式是:调用间隔时间 = duration × frameInterval。

NSTimer

//NSTimer-(void)NSTimerMethod{    //创建定时器    NSTimer *timer = [NSTimer timerWithTimeInterval:0.8 repeats:YES block:^(NSTimer * _Nonnull timer) {        NSLog(@"NSTIMER!");    }];    //定时器添加到主运行循环中    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];    //取消定时器//     [timer invalidate];}

TimerInterval : 执行之前等待的时间。比如设置成1.0,就代表1秒后执行方法

target : 需要执行方法的对象。

selector : 需要执行的方法

repeats : 是否需要循环

调用创建方法后,target对象的计数器会加1,直到执行完毕,自动减1。如果是循环执行的话,就必须手动关闭,否则可以不执行释放方法。

在定时器功能结束以后或者控制器释放需手动释放定时器,不然容易引起内存泄漏.

[timer invalidate];
0 0