NSTimer
2018-03-16 本文已影响0人
zhaihongxia
创建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都会被及时触发