iOS NSTimer的使用

NSTimer 是 iOS 上的一种计时器,通过 NSTimer 对象,可以指定时间间隔,向一个对象发送消息。NSTimer 是比较常用的工具,比如用来定时更新界面,定时发送请求等等。但是在使用过程中,有很多需要注意的地方,稍微不注意就会产生 bug,crash,内存泄漏。本文讲解了使用 NSTimer 的使用和使用时需要注意的问题。

NSTimer * aTimer = [NSTimer scheduledTimerWithTimeInterval:1.0f
                                                        target:self
                                                      selector:@selector(update:)
                                                      userInfo:nil
                                                       repeats:YES];

 
  

1、上述方式为NSTimer的最常用的使用方式,将初始化一个无限循环的 timer,同时投入当前线程的 Runloop 中开始执行。这种无限循环的 timer,会一直执行,需要调用[timer invalidate]显式停止。否则 self 会一直引用着 timer,timer 又引用了 self,导致 self 整个对象泄漏,实际情况中,这个 self 有可能是一个 view,甚至是一个 controller。

[timer invalidate] 要什么时候调用?有些人会在 self 的 dealloc 里面调用,这几乎可以确定是错误的。因为 timer 会引用住 self,在 timer 停止之前,是不会释放 self 的,self 的 dealloc 也不可能会被调用。

正确的做法应该是根据业务需要,在适当的地方启动 timer 和停止 timer。比如 timer 是页面用来更新页面内部的 view 的,那可以选择在页面显示的时候启动 timer,页面不可见的时候停止 timer。

2、开启、关闭计时器

// 这是设置定时器的启动时间,常用来管理定时器的启动与停止
@property (copy) NSDate *fireDate;
      // 启动定时器 
          timer.fireDate = [NSDate distantPast];    
      //停止定时器 
          timer.fireDate = [NSDate distantFuture];
      // 开启 
         [time setFireDate:[NSDate  distanPast]]
      // NSTimer   关闭  
        [time  setFireDate:[NSDate  distantFunture]]
      //继续。
        [timer setFireDate:[NSDate date]]; 

使用-(void)fire方法来立即触发该定时器;在重复执行的定时器中调用此方法后立即触发该定时器,但不会中断其之前的执行计划;

在不重复执行的定时器中调用此方法,立即触发后,就会使这个定时器失效。


 3、Perform Delay

[NSObject performSelector:withObject:afterDelay:] 和 [NSObject performSelector:withObject:afterDelay:inMode:] 我们简称为 Perform Delay,他们的实现原理就是一个不循环(repeat 为 NO)的 timer。所以使用这两个接口的注意事项跟使用 timer 类似。需要在适当的地方调用 [NSObject cancelPreviousPerformRequestsWithTarget:selector:object:]

4、Runloop Mode

创建 NSTimer 或者调用 Perform Delay 方法,要把它添加到指定runloop的指定mode中去,通常是模式是 CFRunloopDefaultMode。Runloop不在 DefaultMode下运行的时候,timer无法触发事件。(比如滚动列表时主线程的 runloop mode 是 CFRunloopTrackingMode)

5、Weak Timer

NSTimer 使用中比较重要的问题是 NSTimer 对 target 是强引用的。timer 如果对 target 是弱引用的话,这些问题就不存在了,这就是 Weak Timer。Weak Timer 的实现方式分为两种,第一种是在 NSTimer 和 target 中间加多一层代理(Proxy),代理作为 target 被 NSTimer 强引用,同时弱引用真正的 target,并对它转发消息。第二种方案是用 dispatch timer 自己实现一遍 timer,具体实现里面,弱引用 target。比如这个:https://github.com/mindsnacks/MSWeakTimer。



你可能感兴趣的:(其他)