关于NSTimer

作者: CharType | 来源:发表于2017-03-26 11:45 被阅读17次

关于NSTimer

在工作中经常会做一些延时任务,或者周期性任务,有时候也需要对取消延时任务操作。

延时任务一般有三种
  • NSObject的
 -(void)performSelector:(SEL)aSelector withObject:(nullable id)anArgument afterDelay:(NSTimeInterval)delay;
  • 使用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;
  • 使用GCD的一些函数

dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(.5f * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{});


> 如果这个任务不需要撤销,使用GCD是最好的选择
如果需要有撤销操作,就不能使用GCD,使用NSObject的函数或者使用NSTimer需要注意一些细节

* 必须有一个活跃的RunLoop, performSelector和NSTimer的一些函数都是基于RunLoop的,主线程的RunLopp是默认启动的,如果放在子线程创建必须手动启动子线程的RunLoop。
* NSTimer的创建和撤销需要放在同一个线程操作,performSelector的创建与撤销必须在同一个线程操作。
* 有内存泄露的潜在风险,scheduledTimerWithTimeInterval函数会对target进行强引用,而NSTimer会被当前的runloop强引用,只有当调用NSTimer的invalidate才能解除掉这个强引用,performSelector也同样会对target进行强引用,必须手动取消才可以解除这个强引用,当我们创建一个NSTimer的时候,我们在当前对象的dealloc函数中invalidate这个timer,看似合理,但是dealloc永远不会被调用,造成了内存泄露

> 看下苹果对NSTimer的invalidate函数介绍
> Discussion
>
This method is the only way to remove a timer from an NSRunLoop object. The NSRunLoop object removes its strong reference to the timer, either just before the invalidate method returns or at some later point.
>
If it was configured with target and user info objects, the receiver removes its strong references to those objects as well.
>
Special Considerations
>
You must send this message from the thread on which the timer was installed. If you send this message from another thread, the input source associated with the timer may not be removed from its run loop, which could prevent the thread from exiting properly.

只有这个函数才能从runloop中删除这个定时器。

>
所以我们使用NSTimer会考虑timer何时释放的问题,我们一般的做法是在页面显示的时候启动这个定时器,页面消失的时候停止这个定时器

但是有的时候有需求,需要定时器不要停止,我们从当前页面push到另外一个页面的时候 定时器不停止。如果停止定时器放在viewWillDisappear函数中时,push到其他页面定时器一样会停止。
>
保证Timer一定会被停止,可以手动停止,就是调用invalidate,可以在页面退出的时候手动的去invalidate,(在back的时候,等等)。
只前遇到这种需求,对Timer做了一个简单的封装,先看代码

BFSTimerextension.h

import <Foundation/Foundation.h>

@protocol BFSTimerextensionDelegate <NSObject>
/**
定时器调用代理函数
/
-(void)timerfucntionCall;
@end
@interface BFSTimerextension : NSObject
@property(nonatomic,weak) id<BFSTimerextensionDelegate> delegate;
/
*
启动一个定时器
@param timeInterval 间隔时间
@param repeats 是否重复
/
-(void)startTimer:(NSTimeInterval)timeInterval repeats:(BOOL)repeats;
/
*
停止这个定时器
*/
-(void)stopTimer;
@end


   BFSTimerextension.m
   

import "BFSTimerextension.h"

@interface BFSTimerextension()
@property (nonatomic, strong) NSTimer *timer;
@end
@implementation BFSTimerextension
-(void)dealloc
{
NSLog(@"被释放");
}

-(void)startTimer:(NSTimeInterval)timeInterval repeats:(BOOL)repeats
{
if(!_timer)
{
_timer = [NSTimer scheduledTimerWithTimeInterval:timeInterval target:self selector:@selector(timerSelectCall) userInfo:nil repeats:repeats];
}
}

-(void)timerSelectCall
{
if(self.delegate && [self.delegate respondsToSelector:@selector(timerfucntionCall)])
{
[self.delegate timerfucntionCall];
}else{
[self.timer invalidate];
self.timer = nil;
}
}

-(void)stopTimer
{
if(self.timer)
{
[self.timer invalidate];
self.timer = nil;
}
}
@end



使用BFSTimerextension创建一个Timer  timer的tagret是BFSTimerextension,如果BFSTimerextension的delegate被释放,timer直接释放掉,我们不用在考虑timer什么时机停止的问题,

注:文中若有错误,请指出,谢谢
代码地址请点击[这里](https://github.com/CharType/Timerextension)





 
 

相关文章

  • NSTimer

    深入NSTimer(iOS)iOS 中的 NSTimer关于NSRunLoop和NSTimer的深入理解

  • Controller销毁NSTimer释放的细节

    关于NSTimer释放和内存泄漏的问题。 @(NSTimer)[内存管理,NSTimer释放,循环引用] 首先需要...

  • NSTimer CADisplayLink GCD计时器的深入探

    关于NSTimer CADisplayLink GCD计时器的杂谈 ** NSTimer ** iOS中最常用的定...

  • 关于NSTimer

    NSTimer 一个计时器,不算常用但也算基础。我想每个开发iOS都应该知道,所以我一般会把他当作一个面试题。可以...

  • 关于NSTimer

    NSTimer使用方式 常用的创建方式有 1+ (NSTimer *)timerWithTimeInterval:...

  • 关于NSTimer

    关于NSTimer 在工作中经常会做一些延时任务,或者周期性任务,有时候也需要对取消延时任务操作。 延时任务一般有...

  • 关于NSTimer

    Timer使用注意事项:1.被VC持有,当页面消失,倒计时未结束,未被销毁,导致VC不被dealloc。VC1推出...

  • 多线程下关于NSTimer不释放的问题

    多线程下关于NSTimer不释放的问题 前言 前段时间由于项目需要,用到NSTimer,考虑到不占用主线程资源,故...

  • 关于NSTimer的循环引用问题

    关于NSTimer的介绍 1、最近在总结知识、好久没记录了,今天抽空记录下NSTimer的使用,首先我们先看下Ap...

  • GCD之timer源码剖析

    参考:从NSTimer的失效性谈起(二):关于GCD Timer和libdispatch

网友评论

    本文标题:关于NSTimer

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