定时器详述

本文详细介绍了iOS开发中常用的三种定时器实现方式:NSTimer、CADisplayLink和GCD。对于NSTimer,讲解了其初始化方法、参数含义以及如何添加到RunLoop。CADisplayLink则是一个与屏幕刷新同步的定时器,适合用于UI重绘和动画。GCD则提供了执行一次性任务和重复任务的定时解决方案。
摘要由CSDN通过智能技术生成

在iOS开发过程中,定时器通常用在这样的情况下:在某个时间后去执行某个方法,或者是按照一个周期循环执行某个方法。大概呢,有以下三种方案:

NSTimer
CADisplayLink
GCD


关于NSTimer

  • NSTimer的初始化方法:

    1
    2
    3
    4
    5
    6
    7
    
    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
    
    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
    
    - (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep NS_DESIGNATED_INITIALIZER;
    
  • 部分参数说明

    repeats: 设置定时器是否循环执行,YES表示循环执行,NO将只执行一次。
    NSTimeInterval: 执行之前等待的时间
    target: 需要执行方法的对象
    selector: 需要执行的方法

  • 说明:不是以scheduledTimerWithTimeInterval:方式初始化的,需要手动地将timer添加到一个runloop中。而以scheduledTimerWithTimeInterval:方式初始化,会自动把timer加入MainRunloop的NSDefaultRunLoopMode中。

    1
    2
    
    NSTimer *timer = [NSTimer timerWithTimeInterval:8 target:self selector:@selector(timerAction) userInfo:nil repeats:YES];   
    [[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];
    
  • 其他方法及属性

    1
    
    - (void)fire;
    
    • 该方法用来立即触发该定时器; 

      官方解释:You can use this method to fire a repeating timer without interrupting its regular firing schedule. If the timer is non-repeating, it is automatically invalidated after firing, even if its scheduled fire date has not arrived.
      意思是说:在重复执行的定时器中调用此方法后立即触发该定时器,但不会中断其之前的执行计划;在不重复执行的定时器中调用此方法,立即触发后,就会使这个定时器失效。

    1
    
    - (void)invalidate;
    
    • 该方法是唯一的,将计时器从runloop中移出的方法。
    1
    2
    
    timer.fireDate = [NSDate distantPast];  // 开启定时器
    timer.fireDate = [NSDate distantFuture]; // 关闭定时器
    
    • 如果希望先停止,然后再某种情况下再次开启运行timer,可以使用属性:fireDate
    1
    2
    3
    4
    5
    6
    7
    8
    
    // 这是一个只读的属性,用来获取定时器调用的间隔时间。
    @property (readonly) NSTimeInterval timeInterval;
    
    // 7.0之后新增的一个属性,因为NSTimer并不完全精准,通过这个值设置误差范围。 
    @property NSTimeInterval tolerance;
    
     // 判断定时器是否有效
    @property (readonly, getter=isValid) BOOL valid;
    

  • CADisplayLink是一个能让我们以和屏幕刷新率同步的频率将特定的内容画到屏幕上的定时器类。CADisplayLink以特定模式注册到runloop后,每当屏幕显示内容刷新结束的时候,runloop就会向CADisplayLink指定的target发送一次指定的selector消息,CADisplayLink类对应的selector就会被调用一次。所以通常情况下,按照iOS设备屏幕的刷新率60次/秒。因此CADisplayLink的selector默认调用周期是每秒60次,这个周期可以通过frameInterval属性设置,CADisplayLink的selector每秒调用次数=60/frameInterval。比如当frameInterval设为2,每秒调用就变成30次。

  • CADisplayLink的方法及属性

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    
    + (CADisplayLink *)displayLinkWithTarget:(id)target selector:(SEL)sel;
    - (void)addToRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode;
    - (void)removeFromRunLoop:(NSRunLoop *)runloop forMode:(NSString *)mode;
    - (void)invalidate;
    
    // 只读的CFTimeInterval值,表示屏幕显示的上一帧的时间戳,这个属性通常被target用来计算下一帧中应该显示的内容。 
    @property(readonly, nonatomic) CFTimeInterval timestamp;
    
    // 表示两次屏幕刷新之间的时间间隔,**该属性在target的selector被首次调用以后才会被赋值。selector的调用间隔时间计算方式是:时间=duration×frameInterval**。 
    @property(readonly, nonatomic) CFTimeInterval duration;
    
    @property(getter=isPaused, nonatomic) BOOL paused;
    
    // 用来设置间隔多少帧调用一次selector方法,默认值是1,即每帧都调用一次。
    @property(nonatomic) NSInteger frameInterval;
    
  • 示例

    1
    2
    3
    4
    5
    6
    7
    
    self.displayLink = [CADisplayLink displayLinkWithTarget:self selector:@selector(handleDisplayLink:)];    
    self.displayLink.frameInterval = 2;
    [self.displayLink addToRunLoop:[NSRunLoop currentRunLoop] forMode:NSDefaultRunLoopMode];
      
    // 关闭定时器
    [self.displayLink invalidate];
    self.displayLink = nil;
    
  • CADisplaylink和NSTimer的区别

    CADisplayLink: 使用场合相对专一,适合做UI的不停重绘,比如自定义动画引擎或者视频播放的渲染。在UI相关的动画或者显示内容使用CADisplayLink显得很方便,因为不需要格外关心屏幕的刷新频率了,它本身就是跟屏幕刷新同步的。
    NSTimer: 使用范围要广泛的多,各种需要单次或者循环定时处理的任务都可以使用。


关于GCD

  • 执行一次

    1
    2
    3
    4
    5
    
    double delayInSeconds = 2.0;
    dispatch_time_t popTime = dispatch_time(DISPATCH_TIME_NOW, delayInSeconds * NSEC_PER_SEC); 
    dispatch_after(popTime, dispatch_get_main_queue(), ^(void){ 
        //执行事件
    });
    
  • 重复执行

    1
    2
    3
    4
    5
    6
    7
    8
    
    NSTimeInterval period = 1.0;
    dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    dispatch_source_t _timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);
    dispatch_source_set_timer(_timer, dispatch_walltime(NULL, 0), period * NSEC_PER_SEC, 0);
    dispatch_source_set_event_handler(_timer, ^{
    	NSLog(@"GCD continue");
    });   
    dispatch_resume(_timer);
    

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值