1 、、、、、
先說一下我的業務需求,最近在做一個小項目,需要用到定時器的功能,NSTimer類,期間,出現了一些小問題,不過最終通過自己的努力,終於做出來了。我想總結一下,我對NSTimer類的學習和理解。
不多說了,先上效果圖
界面元素很簡單,兩個UIButton 開始和暫停,20表示起始倒計時。最終的效果是,按開始按鈕的時候,倒計時開始運行,按暫停按鈕的時候,計時器,停止倒計時。當倒計時為0的時候,彈出一個對話框,提示時間已到。
業務需求很簡單,但是,在我的實現中,卻出現了,一些小錯誤。 主要是暫停鍵不能點擊多次,開始鍵也不能點擊多次,我相信,剛開始,接觸這個NSTimer的人,也會出現這幾個問題。
直接上幾個主要的代碼:
控制器類的.h文件中
@interface sdsViewController : UIViewController<UIAlertViewDelegate>
//定義一個定時器,做為實例變量
@property(nonatomic,retain) NSTimer *timer;
//顯示倒計時當前狀態
@property (retain, nonatomic) IBOutlet UILabel *timeDisplay;
//開始按鈕,響應的action
- (IBAction)startTime:(id)sender;
//暫停按鈕響應的action
- (IBAction)stopTime:(id)sender;
@end
.m中關鍵代碼
開始按鈕 響應代碼:
- (IBAction)startTime:(id)sender {
//如果定時器對象不存在,則創建一個並啟動
if(!_timer){
//創建一個定時器,這個是直接加到當前消息循環中,注意與其他初始化方法的區別
_timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(changeTimeAtTimedisplay) userInfo:nil repeats:YES];
// [_timer fire]; //對於這個fire方法,稍後會詳解,它不是啟動一個定時器,這麼簡單
}
}
//結束按鈕響應代碼:
- (IBAction)stopTime:(id)sender {
if (_timer) {
NSLog(@"調用 self.time為真!!");
//如果定時器在運行
if ([self.timer isValid]) {
NSLog(@"單擊停止按鈕,取消定時器!!");
[self.timer invalidate];
//這行代碼很關鍵
_timer=nil;
}
}
}
一切OK,現在分析程序用到的關鍵地方。
先看看NSTimer類的結構,比較簡單
Tasks
Creating a Timer
//創建一個定時器 ,以下是便利構造器方法,都懂的
+ scheduledTimerWithTimeInterval:invocation:repeats:
+ scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
+ timerWithTimeInterval:invocation:repeats:
+ timerWithTimeInterval:target:selector:userInfo:repeats:
//初始化方法
– initWithFireDate:interval:target:selector:userInfo:repeats:
//是開始一個定時器嗎,恐怕沒那麼簡單????????
Firing a Timer
– fire
//是暫停一個定時器嗎,NO ,是Stop ,寫的很清楚
Stopping a Timer
– invalidate
//關於定時器的以下信息
Information About a Timer
– isValid //是否在運行
– fireDate //Returns the date at which the receiver will fire.
– setFireDate: //重新設置定時器開始運行的時間
– timeInterval //定時器延時時間
– userInfo //其他信息
------------------------------------------------------
2、、、、、、、、、
先說一下,初始化方法
+ scheduledTimerWithTimeInterval:invocation:repeats:
+ scheduledTimerWithTimeInterval:target:selector:userInfo:repeats:
這兩個是創建一個定時器,並加入到當前運行循環中,即我們可以這樣去理解,這樣初始化一個定時器時,在(NSTimeInterval)seconds 時間之後,自動啟動定時器。
而以下兩個初始化方法這不一樣:
+ timerWithTimeInterval:invocation:repeats:
+ timerWithTimeInterval:target:selector:userInfo:repeats:
這兩個同樣是創建,但沒有加入到,運行循環中。class method to create the timer object without scheduling it on a run loop.然後,建立之後,必須(after creating it, you must add the timer to a run loop manually by calling the addTimer:forMode: method of the corresponding NSRunLoop object.),這就是與上面兩個方法的區別。
//創建一個定時器
_timer=[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(changeTimeAtTimedisplay) userInfo:nil repeats:YES];
_timer=[NSTimer timerWithTimeInterval:10 target:self selector:@selector(changeTimeAtTimedisplay) userInfo:nil repeats:YES];
//必須手動加入到當前循環中去
NSRunLoop *runloop=[NSRunLoop currentRunLoop];
[runloop addTimer:_timer forMode:NSDefaultRunLoopMode];
以上兩端代碼效果是一樣的
關於這個方法:
Firing a Timer
– fire
其實他並不是真的啟動一個定時器,從之前的初始化方法中我們也可以看到,建立的時候,在適當的時間,定時器就會自動啟動。那這個方法是干什麼的呢。
You can use this method to fire a repeating timer without interrupting its regular firing schedule. If the timer is non-repeating, it is automatically invalidated after firing, even if its scheduled fire date has not arrived.
這是官方文檔的說法,英文說的很清楚,但我們理解還不是很到位,為了徹底搞懂它的功能。我又做了一個測試。
也是很簡單,把上面那個定時器,改變一點
//初始化的時候創建一個定時器
- (id) initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil{
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self) {
// Custom initialization
//創建一個定時器,
_timer=[NSTimer timerWithTimeInterval:10 target:self selector:@selector(changeTimeAtTimedisplay) userInfo:nil repeats:YES];
//手動加入到循環中
NSRunLoop *runloop=[NSRunLoop currentRunLoop];
[runloop addTimer:_timer forMode:NSDefaultRunLoopMode];
//當然這個定時器會自動啟動,只不多過了十秒之後,才觸發
}
return self
}
當我們單擊“開始”按鈕時,
- (IBAction)startTime:(id)sender {
//只是簡單地調用一下這個方法,看到底功能是什麼
[_timer fire];
}