关于NSTimer分为三个部分去认识:
第一、初始化:
对于NSTimer来说,总共有五种初始化方法
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep NS_DESIGNATED_INITIALIZER;
不用schedule方式初始化的方法,需要在之后手动addTimer:forMode将timer添加到一个runloop里面
但是使用schedule方式初始化的方法,会默认的以NSDefaultRunLoopMode的模式添加到当前的runloop里面
这里就极其有可能发现一个问题。如果当前线程就是主线程,也就是UI线程时,某些UI事件,比如UIScrollView的拖动操作,会将Run Loop切换成NSEventTrackingRunLoopMode模式,在这个过程中,默认的NSDefaultRunLoopMode模式中注册的事件是不会被执行的。也就是说,此时使用scheduledTimerWithTimeInterval添加到Run Loop中的Timer就不会执行。
为了设置一个不被UI干扰的Timer,我们需要手动创建一个Timer,然后使用NSRunLoop的addTimer:forMode:方法来把Timer按照指定模式加入到Run Loop中。这里使用的模式是:NSRunLoopCommonModes,这个模式等效于NSDefaultRunLoopMode和NSEventTrackingRunLoopMode的结合。[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
timer方式创建的对象必须要手动调用fire方法来启动定时器。
schedule方式创建的就不需要手动调用fire方法,它会自动触发。
第二、常用成员变量
@property (copy) NSDate *fireDate;
常用来管理定时器的启动和终止:
timer.fireDate = [NSDate distantPast];//启动
timer.fireDate = [NSDate distantFuture];//停止
@property (readonly) NSTimeInterval timeInterval;
获取定时器调用的间隔时间
@property NSTimeInterval tolerance NS_AVAILABLE(10_9, 7_0);
设置误差范围(IOS7新增)
@property (readonly, getter=isValid) BOOL valid;
获取定时器是否有效
@property (readonly, retain) id userInfo;
获取参数信息
最后、关于内存释放
- (void)invalidate;
这个是唯一一个可以将计时器从runloop中移出的方法
移出之后计时器所在的界面才可以正常释放,不然计时器会一直被保持