美文网首页
NSTimer的用法

NSTimer的用法

作者: 凌巅 | 来源:发表于2017-02-14 19:55 被阅读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循环中。  
    由前面我们可以了解到,通过初始化方法  
    
    
    • (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;
    会将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模式下,在任何情况下都能够正常工作

    
    

    相关文章

      网友评论

          本文标题:NSTimer的用法

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