NSTimer 詳細設置

NSTimer 詳細設置1:http://blog.csdn.net/davidsph/article/details/7899483
NSTimer 詳細設置2:http://blog.csdn.net/davidsph/article/details/7899731

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];

}

結果是,單擊一下按鈕,倒計時減1,單擊一下減1,即它把觸發的時間給提前了,但過十秒後倒計時還會減1,即它只是提前觸發定時器,而不影響之前的那個定時器設置的時間,就好比我們等不及要去看一場球賽,趕緊把車開快些一樣,fire的功能就像讓我們快些到球場,但卻不影響球賽開始的時間。

還記得之前那個初始化定時器時,設置的是YES嗎,當我們,改爲NO時,即不讓它循環觸發時,我們此時再單擊開始按鈕。會猛然發現,倒計時減1了,但當我們再點擊開始按鈕時,會發現倒計時,不會動了。原因是:我們的定時器,被設置成只觸發一次,再fire的時候,觸發一次,該定時器,就被自動銷燬了,以後再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.

這就對了,fire並不是啓動一個定時器,只是提前觸發而已。

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章