NSTimer的用法

2017-02-14  本文已影响561人  凌巅

NSTimer的用法

初始化方法 五个

关于这五个初始化方法我们分为三大类

第一类
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

根据指定参数创建一个NSTimer定时器,但是并没有加入到RunLoop循环中,需要我们手动加入到主循环池中[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode,这是和第二类方法的主要区别

第二类
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;

这两个方法同样依据指定参数创建一个定时器NSTimer,并自动加入到当前的RunLoop循环中,我们不需要手动加入,对比第一类方法

第三类
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(nullable id)ui repeats:(BOOL)rep

这个方法为NSTimer的指定构造方法,我们一般不经常用,供前面四个方法调用。当使用这个方法创建NSTimer实例的时候,需要我们手动加入到主循环池中[NSRunLoop mainRunLoop] addTimer:timer forMode:NSDefaultRunLoopMode

方法参数

1.(NSTimeInterval)ti 定时器的触发时间间隔,如果这个参数<0或者=0,则默认为0.1毫秒
2.(NSInvocation *)invocation NSInvocation对象,构造定时器的回调对象。
3.(BOOL)yesOrNo 是否循环执行,YES循环,NO只执行一次
4.(id)aTarget 定时器回调时发送消息的执行对象,该对象执行(SEL)s方法
5.(SEL)aSelector 定时器回调时所执行的方法
6.(nullable id)userInfo 传递给定时器的参数信息
7.(NSDate *)date 定时器触发的时间

成员方法

- (void)fire;

立即触发此定时器,但并不影响之前设置的定时器时间间隔。如果定时器没有设置循环触发,那么执行此函数后,定时器被自动销毁,以后不会触发了。

- (void)invalidate;

停止定时器,并从循环池中移除这个定时器,从文档中可以看出,这是唯一的方法将定时器从循环池中移除。

成员变量
@property (copy) NSDate *fireDate;

设置定时器的启动时间,常用来管理定时器的启动和停止

//启动定时器

timer.fireDate = [NSDate distantPast];

[timer setFireDate:[NSDate distantPast]];


>//停止定时器

>```
timer.fireDate = [NSDate distantFuture];
或
[timer setFireDate:[NSDate distantFuture]];

//继续

timer.fireDate = [NSDate date];

[timer setFireDate:[NSDate date]];


@property (readonly) NSTimeInterval timeInterval;

只读属性,获取定时器调用的间隔时间

@property NSTimeInterval tolerance

设置定时器的误差范围
  

@property (readonly, getter=isValid) BOOL valid;

定时器是否有效  

@property (nullable, readonly, retain) id userInfo;

获取传入定时器的参数信息


###使用NSTimer的注意事项
#####循环引用导致的内存泄漏  
当我们创建NSTimer的时候,NSTimer会对传入的invocation、target这些参数强引用,直到调用```invalidate```方法,才释放这些对象。这就使得我们在使用NSTimer对象的时候要格外小心。  

例如,如果我们在```viewDidLoad```或者其他的方法中创建了NSTimer实例,但是我们要在```dealloc```中销毁,此时就会出现循环应用。因为,不调用```invalidate```方法,永远进不了```dealloc```方法;而不进入```dealloc```方法,则永远也不会调用```invalidate```方法。这个时候就会出现内存泄漏。  
避免这种情况的最简单的方法就是在```viewDidDisappear```或```viewWillDisappear```方法中调用```invalidate```方法
稍微麻烦一点就是自己对NSTimer进行封装.  

#####添加到RunLoop
NSTimer必须加入到RunLoop循环池中才会起作用,NSTimer其实也是一种事件(资源),如果NSTimer这种资源要起作用的话,就必须加入到RunLoop循环中。  
由前面我们可以了解到,通过初始化方法  

会将timer自动加入到当前的RunLoop中,<strong>如果此时所在的线程不是主线程,则需要我们手动启动当前线程的RunLoop</strong>```[[NSRunLoop currentRunLoop] run]```。  
我们可以在UITableViewCell中这样使用  
   

dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(handleTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] run]; //手动启动当前线程的RunLoop
})

  
  
######RunLoop模式切换    

有这么一种情况,我们在UITableview或者ScrollView中使用NSTimer的时候,当UITableview或者ScrollView滚动的时候,NSTimer停止了。  
比如使用这种方法在主线程中创建NSTimer  

self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(handleTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];

我们将NSTimer添加到RunLoop的默认模式forMode:NSDefaultRunLoopMode,而当我们滚动ScrollView的时候RunLoop将会切换到UITrackingRunLoopMode,所以这个时候NSTimer就停止工作了,滚动完成之后,继续执行,这种情况我们可以这样处理:  

self.timer = [NSTimer timerWithTimeInterval:1.0 target:self selector:@selector(handleTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes]; //将NSTimer放在forMode:NSRunLoopCommonModes模式下,在任何情况下都能够正常工作


上一篇下一篇

猜你喜欢

热点阅读