特別說(shuō)明:原文出處http://www.itdecent.cn/p/3ccdda0679c1
創(chuàng)建
// 創(chuàng)建一個(gè)定時(shí)器,但是么有添加到運(yùn)行循環(huán),我們需要在創(chuàng)建定時(shí)器后手動(dòng)的調(diào)用 NSRunLoop 對(duì)象的 addTimer:forMode: 方法。
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
// 創(chuàng)建一個(gè)timer并把它指定到一個(gè)默認(rèn)的runloop模式中,并且在 TimeInterval時(shí)間后 啟動(dòng)定時(shí)器
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
// 創(chuàng)建一個(gè)定時(shí)器,但是么有添加到運(yùn)行循環(huán),我們需要在創(chuàng)建定時(shí)器后手動(dòng)的調(diào)用 NSRunLoop 對(duì)象的 addTimer:forMode: 方法。
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
// 創(chuàng)建一個(gè)timer并把它指定到一個(gè)默認(rèn)的runloop模式中,并且在 TimeInterval時(shí)間后 啟動(dòng)定時(shí)器
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(nullable id)userInfo repeats:(BOOL)yesOrNo;
// 默認(rèn)的初始化方法,(創(chuàng)建定時(shí)器后,手動(dòng)添加到 運(yùn)行循環(huán),并且手動(dòng)觸發(fā)才會(huì)啟動(dòng)定時(shí)器)
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(nullable id)ui repeats:(BOOL)rep NS_DESIGNATED_INITIALIZER;
開(kāi)啟
// 啟動(dòng) Timer 觸發(fā)Target的方法調(diào)用但是并不會(huì)改變Timer的時(shí)間設(shè)置。 即 time沒(méi)有到達(dá)到,Timer會(huì)立即啟動(dòng)調(diào)用方法且沒(méi)有改變時(shí)間設(shè)置,當(dāng)時(shí)間 time 到了的時(shí)候,Timer還是會(huì)調(diào)用方法。
- (void)fire;
// 設(shè)置定時(shí)器的啟動(dòng)時(shí)間,常用來(lái)管理定時(shí)器的啟動(dòng)與停止
@property (copy) NSDate *fireDate;
timer.fireDate = [NSDate distantPast]; // 開(kāi)啟定時(shí)器
timer.fireDate = [NSDate distantFuture]; // 停止定時(shí)器
[timer setFireDate:[NSDate date]]; // 繼續(xù)定時(shí)器
停止
// 獲取定時(shí)器是否有效
@property (readonly, getter=isValid) BOOL valid;
// 停止 Timer,即將定時(shí)器設(shè)置成無(wú)效 ---> 將定時(shí)器從循環(huán)池中移除
- (void)invalidate;
其他屬性
// 這個(gè)是一個(gè)只讀屬性,獲取定時(shí)器調(diào)用間隔時(shí)間
@property (readonly) NSTimeInterval timeInterval;
// 這是7.0之后新增的一個(gè)屬性,因?yàn)镹STimer并不完全精準(zhǔn),通過(guò)這個(gè)值設(shè)置誤差范圍
@property NSTimeInterval tolerance NS_AVAILABLE(10_9, 7_0);
注意
參數(shù)repeats是指定是否循環(huán)執(zhí)行,YES將循環(huán),NO將只執(zhí)行一次。
timerWithTimeInterval這兩個(gè)類(lèi)方法創(chuàng)建出來(lái)的對(duì)象如果不用 addTimer: forMode方法手動(dòng)加入主循環(huán)池中,將不會(huì)循環(huán)執(zhí)行。
scheduledTimerWithTimeInterval 這兩個(gè)方法會(huì)將定時(shí)器添加到當(dāng)前的運(yùn)行循環(huán),運(yùn)行循環(huán)的模式為默認(rèn)模式。如果需要第一次就執(zhí)行一次,需要調(diào)用開(kāi)啟定時(shí)器的方法。
init方法需要手動(dòng)加入循環(huán)池,它會(huì)在設(shè)定的啟動(dòng)時(shí)間啟動(dòng)。
在頁(yè)面釋放前先釋放定時(shí)器。
內(nèi)存釋放問(wèn)題
- 如果我們啟動(dòng)了一個(gè)定時(shí)器,在某個(gè)界面釋放前,將這個(gè)定時(shí)器停止,甚至置為nil,都不能使這個(gè)界面釋放,原因是系統(tǒng)的循環(huán)池中還保有這個(gè)對(duì)象。
NSTimer為什么要添加到RunLoop中才會(huì)有作用
1、NSTimer其實(shí)也是一種資源(事件),我們會(huì)發(fā)現(xiàn)所有的source(事件)如果要起作用,就得加到runloop中,而且此runloop應(yīng)該是有效的,執(zhí)行著的。
2、同理timer這種資源要想起作用,那肯定也需要加到runloop中才會(huì)有效。
3、如果一個(gè)runloop里面不包含任何資源(事件)的話(huà),運(yùn)行該runloop時(shí)會(huì)處于一種休眠狀態(tài)等待下一個(gè)事件。所以如果創(chuàng)建了timer但是不添加runloop的話(huà),timer資源處于一種閑置等待狀態(tài)。
Code
//創(chuàng)建timer
_requestTimer = [NSTimer scheduledTimerWithTimeInterval:requestInterval target:self selector:@selector(requestDriverPosition) userInfo:nil repeats:YES];
_requestTimer.fireDate = [NSDate distantPast]; // 啟動(dòng)timer
//移除timer
- (void)removeTimer {
if (_requestTimer) {
_requestTimer.fireDate = [NSDate distantFuture]; //停止定時(shí)器
[_requestTimer invalidate];
_requestTimer = nil;
}
}