定时器详述

来源:互联网 发布:口碑和淘宝外卖一样么 编辑:程序博客网 时间:2024/06/10 04:16

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

NSTimer
CADisplayLink
GCD


关于NSTimer

  • NSTimer的初始化方法:

    1234567
    + (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中。

    12
    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中移出的方法。
    12
    timer.fireDate = [NSDate distantPast];  // 开启定时器timer.fireDate = [NSDate distantFuture]; // 关闭定时器
    • 如果希望先停止,然后再某种情况下再次开启运行timer,可以使用属性:fireDate
    12345678
    // 这是一个只读的属性,用来获取定时器调用的间隔时间。@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的方法及属性

    123456789101112131415
    + (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;
  • 示例

    1234567
    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

  • 执行一次

    12345
    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){     //执行事件});
  • 重复执行

    12345678
    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);

0 0
原创粉丝点击