1 五种初始化方法
※创建定时器的time-类方法,需要手动fire开启定时器,将执行方法封装到NSInvocation中
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
※创建定时器的time-类方法,需要手动fire开启定时器
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
※创建定时器的scheduled-类方法,不需要手动fire开启定时器,将执行方法封装到NSInvocation中
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
※创建定时器的scheduled-类方法,不需要手动fire开启定时器
+ (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;
注意:这五种初始化方法的异同:
1、参数repeats是指定是否循环执行,YES将循环,NO将只执行一次。
2、timerWithTimeInterval这两个类方法创建出来的对象如果不用 addTimer: forMode方法手动加入主循环池中,将不会循环执行。如果将定时器加到了主循环池中,则不需要手动调用fire启动定时器;相反,如果没有将定时器加到主循环池中,则需要手动调用fire,但是此时定时器会启动执行一次。
3、scheduledTimerWithTimeInterval这两个方法不需要手动调用fire,会自动执行,并且自动加入主循环池。
4、init方法需要手动加入循环池,它会在设定的启动时间启动。
5、子线程中开启定时器需要手动加入当前runloop中,并且需要开启子线程的Runloop
定时器引起循环引用的解决方法:
+ (NSTimer *)sf_scheduledTimerWithTimeInterval:(NSTimeInterval)interval block:(void (^)())block repeats:(BOOL)repeats{
return [self scheduledTimerWithTimeInterval:interval target:self selector:@selector(sf_blockInvoke:) userInfo:[block copy] repeats:repeats];
}
+ (NSTimer *)sf_timerWithTimeInterval:(NSTimeInterval)seconds block:(void (^)(NSTimer *))block repeats:(BOOL)repeats{
return [self timerWithTimeInterval:seconds target:self selector:@selector(sf_blockInvoke:) userInfo:[block copy] repeats:repeats];
}
+ (void)sf_blockInvoke:(NSTimer*)timer{
if (timer.userInfo) {
void(^block) () = timer.userInfo;
block();
}
}