NSTimer 的使用

使用方法

+ (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

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1.NSTimer的介绍 (1.)8种创建方法 <1> + (NSTimer *)timerWithTimeInt...
    liangZhen阅读 7,734评论 0赞 6
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 11,913评论 1赞 32
  • NSTimer继承自NSObject,用于创建定时器对象,以提供执行延迟动作或周期性动作的方法。通常情况下,创建的...
    蹲瓜阅读 6,432评论 0赞 5
  • 定时器的用法 系统提供了8个创建方法,6个类创建方法,2个实例初始化方法。有三个方法直接将timer添加到...
    gpylove阅读 1,946评论 1赞 3
  • 这本加缪的《西西弗神话》,全书不过一百多页,却是加缪的成名之作,经久不衰。加缪在书中也明确的说明了自己的观点:人生...
    湛辉阅读 1,725评论 0赞 5

友情链接更多精彩内容