美文网首页
NSTimer 的使用

NSTimer 的使用

作者: yyggzc521 | 来源:发表于2019-04-20 17:13 被阅读0次

使用方法

+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

scheduledTimerWith和timerWith和区别

NSTimer是加到runloop中执行的。

  1. scheduledTimerWith
    函数说明,创建并安排到runloop的default mode中

Creates a timer and schedules it on the current run loop in the default mode

  1. timerWithTimeInterval
    如果我们调用的是timerWith接口,就需要自己加入runloop
NSTimer *timer  =  [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(Timered) userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode];

GCD定时器

如何使用

GCD中的Dispatch Source其中的一种类型是DISPATCH_SOURCE_TYPE_TIMER,可以实现定时器的功能。注意的是需要把timer声明为属性,否则,由于这种timer并不是添加到runloop中的,直接就被释放了。

GCD定时器的好处是,他并不是加入runloop执行的,因此子线程也可以使用。也不会引起循环引用的问题。

WS(weakSelf);
timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, dispatch_get_main_queue());
dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 5 * NSEC_PER_SEC, 1 * NSEC_PER_SEC);
dispatch_source_set_event_handler(timer, ^{
    [weakSelf commentAnimation];
});
dispatch_resume(timer);

注意事项

子线程启动NSTimer

主线程默认启动了runloop,子线程没有默认的runloop,因此,在子线程启动定时器是不生效的
解决方案

    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        NSTimer* timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(Timered:) userInfo:nil repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
        [[NSRunLoop currentRunLoop] run];
    });

循环引用

NSTimer的target被强引用了,而通常target就是所在的控制器,他又强引用了timer,造成了循环引用

不是所有的NSTimer都会造成循环引用。就像不是所有的block都会造成循环引用一样
以下两种timer不会有循环引用:

  • 非repeat类型的。非repeat类型的timer不会强引用target,因此不会出现循环引用。
  • block类型的,新api。iOS 10之后才支持,因此对于还要支持老版本的app来说,这个API暂时无法使用。当然,block内部的循环引用也要避免

不是解决了循环引用,target就可以释放了,别忘了在持有timer的类dealloc的时候执行invalidate。

NSTimer* timer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(Timered:) userInfo:nil repeats:YES];

如上面代码,这个timer并没有被self引用,那么为什么self不会被释放呢?因为timer被加到了runloop中,timer又强引用了self,所以timer一直存在的话,self也不会释放。

参考资料

https://www.jianshu.com/p/3ccdda0679c1

相关文章

  • NSTimer的循环引用

    NSTimer基本使用 NSTimer与RunLoop NSTimer 循环引用的问题 如何在子线程使用NSTim...

  • iOS-NSTimer-循环引用问题

    在使用NSTimer的时候,NSTimer会生成指向其使用者的引用,而其使用者如果也引用了NSTimer,那么就会...

  • NSTimer的使用

    NSTimer 的使用 为什么会写NSTimer呢? 原因很简单, 这里有坑! NSTimer 使用的顺序 创建N...

  • 倒计时实现方法两个

    方法1:使用NSTimer来实现 主要使用的是NSTimer的scheduledTimerWithTimeInte...

  • 内存管理总结

    CADisplayLink、NSTimer使用注意 CADisplayLink、NSTimer会对target产生...

  • Objective-C基础-内存管理

    1、CADisplayLink、NSTimer使用 CADisplayLink、NSTimer会对target产生...

  • CADisplayLink、NSTimer使用注意

    CADisplayLink、NSTimer使用注意 CADisplayLink、NSTimer会对target产生...

  • 底层-内存管理

    CADisplayLink、NSTimer使用注意 CADisplayLink、NSTimer会对target产生...

  • 内存管理

    CADisplayLink、NSTimer使用注意 CADisplayLink、NSTimer会对target产生...

  • iOS内存管理

    CADisplayLink、NSTimer使用注意 CADisplayLink、NSTimer会对target产生...

网友评论

      本文标题:NSTimer 的使用

      本文链接:https://www.haomeiwen.com/subject/fpadhqtx.html