NSTimer

作者: zhaihongxia | 来源:发表于2018-03-16 16:28 被阅读0次

    创建NSTimer
    创建NSTimer的常用方法是

    + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats
    

    创建NSTimer的不常用方法是

    + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats
    

    - (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats
    
    

    他们的区别很简单:

    scheduledTimerWithTimeInterval相比它的小伙伴们不仅仅是创建了NSTimer对象, 还把该对象加入到了当前的runloop中!
    
    NSTimer只有被加入到runloop, 才会生效, 即NSTimer才会被真正执行
    

    所以说, 如果你想使用timerWithTimeInterval或initWithFireDate的话, 需要使用NSRunloop的以下方法将NSTimer加入到runloop中

    - (void)addTimer:(NSTimer *)aTimer forMode:(NSString *)mode
    

    invalidate与fire

    invalidate销毁NSTimer 不能直接置为nil
    1.创建NSTimer, 加入到runloop后, 除了ViewController之外iOS系统也会强引用NSTimer对象
    2.当调用invalidate方法时, 移除runloop后, iOS系统会解除对NSTimer对象的强引用, 当ViewController销毁时, ViewController和NSTimer就都可以释放了
    3.当将NSTimer对象置nil时, 虽然解除了ViewController对NSTimer的强引用, 但是iOS系统仍然对NSTimer和ViewController存在着强引用关系
    4.iOS系统对ViewController的强引用, 不是指为了实现View显示的强引用, 而是指iOS为了实现NSTimer而对ViewController进行的额外强引用
    
    fire 开启timer
    [timer fire]
    

    综上所述, 销毁NSTimer的正确姿势应该是

    [_timer invalidate]; // 真正销毁NSTimer对象的地方
    _timer = nil; // 对象置nil是一种规范和习惯
    

    销毁NSTimer的时机也是至关重要的!

    1.销毁NSTimer的代码放到ViewController的dealloc方法里, 你会发现dealloc还是永远不会走的
    2.要将上述代码放到ViewController的其他生命周期方法里, 例如ViewWillDisappear中
    

    NSTimer与runloop

    runloop会运行在不同的mode, 简单来说有以下两种mode
    1.NSDefaultRunLoopMode, 默认的mode
    2.UITrackingRunLoopMode, 当处理UI滚动操作时的mode
    
    所以scheduledTimerWithTimeInterval创建的NSTimer在UI滚动时, 是不会被及时触发的, 因为此时NSTimer被加到了default mode
    

    想要runloop运行在UITrackingRunLoopMode时, 仍然及时触发NSTimer那应该怎么办呢?

    在创建完NSTimer后, 自己加入到指定的runloop mode
    [[NSRunLoop currentRunLoop] addTimer:_timer forMode:NSRunLoopCommonModes];
    

    NSRunLoopCommonModes又是什么鬼? 不是说好的只有两种mode么?

    1.注意这里的复数形式modes, 说明它不是一个mode, 它是mode的集合!
    2.通常情况下NSDefaultRunLoopMode和UITrackingRunLoopMode都已经被加入到了common modes集合中, 所以不论runloop运行在哪种mode下, NSTimer都会被及时触发
    

    相关文章

      网友评论

          本文标题:NSTimer

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