計時器

很詳細(xì)的計時器文章 介紹了三種定時器方法
http://www.itdecent.cn/p/c167ca4d1e7e

  • NSTimer
    必須加入Runloop、
    存在延遲、
    UIScrollView滑動會暫停計時(若不想被UIScrollView滑動影響,需要將 timer 添加再到 UITrackingRunLoopMode 或 直接添加到NSRunLoopCommonModes 中)
  • GCD計時器 精度最好 ?
  • CADisplayLink
    刷新頻率固定 (取決CPU的忙碌程度)、
    屏幕刷新時調(diào)用 (CADisplayLink在正常情況下會在每次刷新結(jié)束都被調(diào)用,精確度相當(dāng)高。但如果調(diào)用的方法比較耗時,超過了屏幕刷新周期,就會導(dǎo)致跳過若干次回調(diào)調(diào)用機(jī)會)、
    適合做界面渲染(CADisplayLink可以確保系統(tǒng)渲染每一幀的時候我們的方法都被調(diào)用,從而保證了動畫的流暢性。)

后臺常駐 的問題 看到了一篇文章
https://www.cnblogs.com/lyanet/archive/2013/03/26/2983079.html
還有另一篇
http://www.itdecent.cn/p/d1ecc467faff
通過這兩個
蘋果文檔說到任何應(yīng)用都有3分鐘的后臺執(zhí)行任務(wù)的時間 。。。跟蘋果借點時間用用。。。不用配置info.plist 避免因為配置后臺長期運行后,蘋果審查出你濫用api(如果你配置了 項目中必須要有相關(guān)的功能)
第一篇提到了 應(yīng)該在長期任務(wù)結(jié)束后,我們需要做一些事情進(jìn)行清理:

  1. 結(jié)束所有的線程和定時器,不管他們是基礎(chǔ)定時器還是GCD中創(chuàng)建的。

  2. 調(diào)用UIApplication的endBackgroundTask:方法來結(jié)束后臺任務(wù)。

  3. 將任務(wù)標(biāo)識設(shè)置為UIBackgroundTaskInvalid,標(biāo)志我們的任務(wù)結(jié)束。

最后,當(dāng)我們的應(yīng)用回到前臺,如果我們的后臺任務(wù)還在執(zhí)行中,我們需要確保我們在干掉它:

主要代碼放在下邊以防丟失

  • 3分鐘的后臺執(zhí)行任務(wù)
@property (nonatomic, unsafe_unretained) UIBackgroundTaskIdentifier backgroundTaskIdentifier;


- (void)applicationDidEnterBackground:(UIApplication *)application {
    
    UIApplication*   app = [UIApplication sharedApplication];

    __weak typeof(self)weakSelf = self;
    
    self.backgroundTaskIdentifier = [app beginBackgroundTaskWithExpirationHandler:^{
        dispatch_async(dispatch_get_main_queue(), ^{            if (weakSelf.backgroundTaskIdentifier != UIBackgroundTaskInvalid)
        {
            weakSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
        }
        });
    }];

    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), ^{
        dispatch_async(dispatch_get_main_queue(), ^{            if (weakSelf.backgroundTaskIdentifier != UIBackgroundTaskInvalid)
        {
            weakSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
        }
        });
    });
}


- (void)applicationWillEnterForeground:(UIApplication *)application {
    
    if (self.backgroundTaskIdentifier != UIBackgroundTaskInvalid){
        
        [self endBackgroundTask];
        
    }

}
- (void) endBackgroundTask{
    
    dispatch_queue_t mainQueue = dispatch_get_main_queue();
    
    __weak typeof(self)weakSelf = self;

    dispatch_async(mainQueue, ^(void) {
        
        if (weakSelf != nil){
            
            [[UIApplication sharedApplication] endBackgroundTask:weakSelf.backgroundTaskIdentifier];
            
            weakSelf.backgroundTaskIdentifier = UIBackgroundTaskInvalid;
            
        }
        
    });
    
}
#pragma mark - 定時器(GCD)
- (void)creatTimer{
    
    //設(shè)置倒計時時間
    //__block 如果修飾指針時,指針相當(dāng)于弱引用,指針對指向的對象不產(chǎn)生引用計數(shù)的影響
    //通過檢驗發(fā)現(xiàn),方法調(diào)用后,timeout會先自動-1,所以如果從30秒開始倒計時timeout應(yīng)該寫31
    __block int timeOut = 31;
    
    //獲取全局隊列
    dispatch_queue_t global = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
    
    //創(chuàng)建一個定時器,并將定時器的任務(wù)交給全局隊列執(zhí)行(并行,不會造成主線程阻塞)
    dispatch_source_t timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, global);

    //設(shè)置觸發(fā)的間隔時間
//    dispatch_source_set_timer(timer, DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC, 0 * NSEC_PER_SEC);
    
    dispatch_source_set_timer(timer, dispatch_walltime(NULL, 0), 1.0 * NSEC_PER_SEC, 0); //每秒執(zhí)行
    
    //1.0 * NSEC_PER_SEC  代表設(shè)置定時器觸發(fā)的時間間隔為1s
    //0 * NSEC_PER_SEC    代表時間允許的誤差是 0s
    
    //block內(nèi)部 如果對當(dāng)前對象的強(qiáng)引用屬性修改,應(yīng)該使用 __weak typeof(self)weakSelf 修飾 避免循環(huán)引用
    __weak typeof(self)weakSelf = self;
    
    //設(shè)置定時器觸發(fā)事件
    dispatch_source_set_event_handler(timer, ^{

        //倒計時 刷新UI,當(dāng)?shù)褂嫊r為0時,結(jié)束倒計時
        
        //1.每調(diào)用一次 時間-1
        timeOut --;
        
        //2.對timeOut 進(jìn)行判斷時間是停止倒計時 還是修改UI
        if (timeOut <= 0) {
            
            //停止倒計時時
            
            //關(guān)閉定時器
            dispatch_source_cancel(timer);
            
            //主線程更新UI
            dispatch_async(dispatch_get_main_queue(), ^{
               
                
            });
            
        }else{
            //主線程更新UI
            dispatch_async(dispatch_get_main_queue(), ^{
                
                
            });
        }
        
    });
    
    dispatch_resume(timer);
    
}
最后編輯于
?著作權(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ù)。

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