創建timer對象的三種方法
一、這兩個類方法創建一個timer並把它指定到一個默認的runloop模式中
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
二、這兩個類方法創建一個timer的對象,不把它指定到哪個runloop. (當創建之後,你必須手動的調用NSRunLoop下對應的方法 addTimer:forMode:去將它指定到一個runloop模式中.)
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
+ (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
三、創建一個NSTimer的實例 (當創建之後,你必須手動的調用NSRunLoop下對應的方法 addTimer:forMode: 去將它指定到一個runloop模式中.)
- (instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep;
通常使用
+ (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;
TimeInterval:時間間隔,浮點型的值。小於0時系統默認爲0.1。用於指定沒間隔該時間段觸發一次指定的方法
target:方法作用對象比如self
selector:作用方法
userInfo:當定時器失效時,由你指定的對象保留和釋放該定時器。通常爲nil
repeats:YES時,不斷循環直至計時器失效或被釋放。NO時只循環一次就失效
其餘方法介紹
- (void)fire; --- 立即觸發計時器
- (void)invalidate; --- 停止計時並使觸發器失效
- (BOOL)isValid; --- 判斷觸發器是否有效
- (NSTimeInterval)timeInterval; --- 觸發間隔時間
- (id)userInfo; --- 一般爲nil
- (NSDate *)fireDate; //開始時間
- (void)setFireDate:(NSDate *)date; //設置fireData,其實暫停、開始會用到
定時器暫停與開始的簡要寫法
[timer setFireDate:[NSDate distantPast]]; //開啓
[timer setFireDate:[NSDate date]];//繼續。
[timer setFireDate:[NSDate distantFuture]]; //暫停
暫停之後計時器仍然有效,而如果用invalidate則會失效,在invalidate之前最好先用isValid先判斷是否還在線程中
if ([timer isValid] ==YES) {
[timer invalidate];
timer =nil;
}
例子:比如在頁面消失的時候關閉定時器,然後等頁面再次打開的時候,又開啓定時器。
(主要是爲了防止它在後臺運行,暫用CPU)可以使用下面的代碼實現:
//頁面將要進入前臺,開啓定時器
-(void)viewWillAppear:(BOOL)animated
{
//開啓定時器
[timer setFireDate:[NSDate distantPast]];
}
//頁面消失,進入後臺不顯示該頁面,關閉定時器
-(void)viewDidDisappear:(BOOL)animated
{
//關閉定時器
[timer setFireDate:[NSDate distantFuture]];
}
最近我在改一個bug,在一個UIViewController上有一個定時器,在執行輪播圖片。push到別的UIViewController的時候,暫停定時器(NSTimer);pop回來的時候,開啓定時器(NSTimer)。這個bug是:push到別的UIViewController暫定定時器(NSTimer),有時候有作用,有時候沒有作用。開始我以爲是NSTimer運行的runLoop有問題,最後發現是別的地方導致這個bug的。不過正好,我們來一起了解一下NSTimer。
創建一個定時器(NSTimer)
- (void)viewDidLoad {
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(actionTimer:) userInfo:nil repeats:YES];
}
- (void)actionTimer:(NSTimer *)timer
{
}
NSTimer默認運行在default mode下,default mode幾乎包括所有輸入源(除NSConnection) NSDefaultRunLoopMode模式。
actionTimer方法會每隔1s中被調用一次。NSTimer使用起來是不是非常簡單。這是NSTimer比較初級的應用。
當主界面被滑動時NSTimer失效了
主界面被滑動是什麼意思呢?就是說主界面有UITableView或者UIScrollView,滑動UITableView或者UIScrollView。這個時候NSTimer失效了。
我們來寫一個demo,在一個有UITableView的UIViewController上啓動定時器,每1s數字加1,並將這個數字顯示在UILabel上面.
- (void)viewDidLoad {
[super viewDidLoad];
[NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(actionTimer:) userInfo:nil repeats:YES];
}
- (void)actionTimer:(NSTimer *)timer
{
self.number++;
self.label.text = [NSString stringWithFormat:@%d,self.number];
NSLog(@%d,self.number);
}
這樣當用戶在拖動UITableView處於UITrackingRunLoopMode時,NSTimer就失效了,不能fire。self.label上的數字也就無法更新。
修改NSTimer的runLoop
解決方法就是將其加入到UITrackingRunLoopMode模式或NSRunLoopCommonModes模式中。
[[NSRunLoop currentRunLoop] addTimer:timer forMode:UITrackingRunLoopMode];
或者
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
NSRunLoopCommonModes:是一個模式集合,當綁定一個事件源到這個模式集合的時候就相當於綁定到了集合內的每一個模式。