iOS之NSTimer

??????You use the NSTimer class to create timer objects or, more simply, timers. A timer waits until a certain time interval has elapsed and then fires, sending a specified message to a target object. For example, you could create an NSTimer object that sends a message to a window, telling it to update itself after a certain time interval.
???????你可以使用NSTimer類創(chuàng)建計時器對象。等到一定的時間間隔時計時器運(yùn)行,發(fā)送一個消息到指定目標(biāo)對象。例如,您可以創(chuàng)建一個NSTimer對象發(fā)送一個消息給窗口,告訴它一定時間間隔后更新。

1. 常用定時器的創(chuàng)建

當(dāng)定時器創(chuàng)建完(不用scheduled 的,添加到 runloop 中)后,該定時器將在初始化時指定的 timeInterval 秒后自動觸發(fā)。如果 NSTimer 的觸發(fā)時間到的時候,runloop 在阻塞狀態(tài),觸發(fā)時間就會推遲到下一個 runloop 周期。

1. scheduled 方式 (可單次執(zhí)行)

  • 創(chuàng)建并啟動定時器。
  • 默認(rèn)將定時器以 NSDefaultRunLoopMode 模式添加到運(yùn)行循環(huán)。
  • 發(fā)生用戶交互的時候,定時器會被暫停。
 /*
        + (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti 
                                             target:(id)aTarget 
                                           selector:(SEL)aSelector 
                                           userInfo:(id)userInfo 
                                            repeats:(BOOL)yesOrNo;

        參數(shù):
            TimeInterval:觸發(fā)時間,單位秒
            target:定時起觸發(fā)對象
            selector:定時器響應(yīng)方法
            userInfo:用戶信息
            repeats:是否重復(fù)執(zhí)行,YES 每個指定的時間重復(fù)執(zhí)行,NO 只執(zhí)行一次
    */

    // 創(chuàng)建并啟動定時器
    NSTimer *timer = [NSTimer scheduledTimerWithTimeInterval:2.0 
                                                      target:self
                                                    selector:@selector(updateTimer:) 
                                                    userInfo:nil 
                                                     repeats:YES];

2. timer 方式

  • 創(chuàng)建定時器,添加到運(yùn)行循環(huán)后啟動定時器。
  • 將定時器以指定的模式添加到運(yùn)行循環(huán)。
/*
        + (NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti 
                                    target:(id)aTarget 
                                  selector:(SEL)aSelector 
                                  userInfo:(nullable id)userInfo 
                                   repeats:(BOOL)yesOrNo;

        - (void)addTimer:(NSTimer *)timer forMode:(NSString *)mode;

        NSDefaultRunLoopMode:發(fā)生用戶交互的時候,時鐘會被暫停。時鐘,網(wǎng)絡(luò)。          
        NSRunLoopCommonModes:發(fā)生用戶交互的時候,時鐘仍然會觸發(fā),如果時鐘觸發(fā)方法非常耗時,
                              使用此方式時用戶操作會造成非常嚴(yán)重的卡頓。用戶交互,響應(yīng)級別高。  
    */

    // 創(chuàng)建定時器
    NSTimer *timer = [NSTimer timerWithTimeInterval:2.0
                                             target:self
                                           selector:@selector(updateTimer:)
                                           userInfo:nil
                                            repeats:YES];

    // 將定時器添加到運(yùn)行循環(huán)
    [[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

2. 官方給定的5個初始化定時器方法

  1. +(NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;
```
- (void)viewDidLoad {
[super viewDidLoad];
//初始化一個Invocation對象
NSInvocation * invo = [NSInvocation invocationWithMethodSignature:[[self class] instanceMethodSignatureForSelector:@selector(init)]];
[invo setTarget:self];
[invo setSelector:@selector(myLog)];
NSTimer * timer = [NSTimer timerWithTimeInterval:1 invocation:invo repeats:YES];
//加入主循環(huán)池中
[[NSRunLoop mainRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];
//開始循環(huán)
[timer fire];

}


2.  +(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti invocation:(NSInvocation *)invocation repeats:(BOOL)yesOrNo;

    ```
  NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:1 
                                                   invocation:invo
                                                      repeats:YES];
  1. +(NSTimer *)timerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

    NSTimer * timer = [NSTimer timerWithTimeInterval:1 
                                              target:self 
                                            selector:@selector(myLog) 
                                            userInfo:nil
                                             repeats:NO]
    
  2. +(NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)ti target:(id)aTarget selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)yesOrNo;

    NSTimer * timer = [NSTimer scheduledTimerWithTimeInterval:1
                                                       target:self
                                                     selector:@selector(myLog:)
                                                     userInfo:@"123"
                                                      repeats:YES]
    
  3. -(instancetype)initWithFireDate:(NSDate *)date interval:(NSTimeInterval)ti target:(id)t selector:(SEL)s userInfo:(id)ui repeats:(BOOL)rep

NSTimer * timer = [[NSTimer alloc]initWithFireDate:[NSDate distantPast]
interval:1
target:self
selector:@selector(myLog:)
userInfo:nil
repeats:YES];

[[NSRunLoop mainRunLoop]addTimer:timer forMode:NSDefaultRunLoopMode];
```

<font style="color:brown" size='4'>注意:</font>這五種初始化方法的異同:

  1. 參數(shù)repeats是指定是否循環(huán)執(zhí)行,YES將循環(huán),NO將只執(zhí)行一次。
  2. timerWithTimeInterval這兩個類方法創(chuàng)建出來的對象如果不用 addTimer: forMode方法手動加入主循環(huán)池中,將不會循環(huán)執(zhí)行。并且如果不手動調(diào)用fair,則定時器不會啟動。
  3. scheduledTimerWithTimeInterval這兩個方法不需要手動調(diào)用fair,會自動執(zhí)行,并且自動加入主循環(huán)池。
  4. init方法需要手動加入循環(huán)池,它會在設(shè)定的啟動時間啟動。

3. 定時器的開啟暫停關(guān)閉和屬性變量

  1. 啟動定時器
[timer setFireDate:[NSDate distantPast]];
  1. 暫停定時器

    [timer setFireDate:[NSDate distantFuture]];
    
  2. 關(guān)閉定時器,永久關(guān)閉定時器

    [timer invalidate];
    
  3. 屬性變量

    • 這是設(shè)置定時器的啟動時間,常用來管理定時器的啟動與停止

      @property (copy) NSDate *fireDate;
      
      //啟動定時器
      timer.fireDate = [NSDate distantPast];
      //停止定時器
      timer.fireDate = [NSDate distantFuture];
      
    • 這個是一個只讀屬性,獲取定時器調(diào)用間隔時間。

      @property (readonly) NSTimeInterval timeInterval; 
      
      
    • 這是7.0之后新增的一個屬性,因為NSTimer并不完全精準(zhǔn),通過這個值設(shè)置誤差范圍

      @property NSTimeInterval tolerance;
      
    • 獲取定時器是否有效

      @property (readonly, getter=isValid) BOOL valid;
      
    • 獲取參數(shù)信息

      @property (readonly, retain) id userInfo;
      

4. 在子線程中創(chuàng)建定時器

//  創(chuàng)建子線程
    dispatch_async(dispatch_get_global_queue(0, 0), ^{
        
        // 在子線程創(chuàng)建定時器
        /*
         scheduled 或 timer 方式創(chuàng)建
         */
        self.timer = [NSTimer timerWithTimeInterval:1.0
                                             target:self
                                           selector:@selector(updateTimer:)
                                           userInfo:nil
                                            repeats:YES];
        [[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSDefaultRunLoopMode];
        
        // 啟動子線程的運(yùn)行循環(huán)
        /*
         這句代碼就是一個死循環(huán)!如果不停止運(yùn)行循環(huán),不會執(zhí)行添加到此句之后的 任何代碼
         */
        CFRunLoopRun();
                
        // 停止子線程運(yùn)行循環(huán)之前,不會執(zhí)行添加到此處的任何代碼
    });
    
    
// 定時器執(zhí)行操作方法
- (void)updateTimer {

        static int num = 0;
        num++;

        // 滿足條件后,停止當(dāng)前的運(yùn)行循環(huán)
        if (num == 8) {

            // 停止當(dāng)前的運(yùn)行循環(huán)
            /*
                一旦停止了運(yùn)行循環(huán),后續(xù)代碼能夠執(zhí)行,執(zhí)行完畢后,線程被自動銷毀
            */
            CFRunLoopStop(CFRunLoopGetCurrent());
        }
    }

5. 定時器的銷毀

在官方文檔中我們可以看到 [timer invalidate]是唯一的方法將定時器從循環(huán)池中移除。

如果我們啟動了一個定時器,在某個界面釋放前,將這個定時器停止,甚至置為nil,都不能是這個界面釋放,原因是系統(tǒng)的循環(huán)池中還保有這個對象,我們需要在下面三個方法中

  • 定時器執(zhí)行方法

  • 視圖顯示ViewDidDisappera方法

  • deallock 方法

實現(xiàn)如下代碼進(jìn)行定時器的徹底釋放:

    if (timer.isValid) {
        [timer invalidate];
    }
    timer=nil;

6. 其他實現(xiàn)定時功能的方法

  1. performSelector 延時調(diào)用

    /*
        1.5 秒后自動調(diào)用 self 的 hideHUD 方法
    */
    [self performSelector:@selector(hideHUD) withObject:nil afterDelay:1.5];
    
    // 取消延時調(diào)用
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(hideHUD) object:nil];
    
  2. GCD 多線程

    
    /*
        1.5 秒后自動執(zhí)行 block 里面的代碼
    */
     dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.5 * NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
    
        self.hud.alpha = 0.0;
        });
    

3. NSTimer 定時器

    ```
    /*
        1.5 秒后自動調(diào)用 self 的 hideHUD 方法
    */
    [NSTimer scheduledTimerWithTimeInterval:1.5 
                                     target:self 
                                   selector:@selector(hideHUD)
                                   userInfo:nil 
                                    repeats:NO];
    ```



最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時請結(jié)合常識與多方信息審慎甄別。
平臺聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容