NSTimer不準問題解決

NSTimer導致誤差的原因:

1、NSTimer加在main runloop中,模式是NSDefaultRunLoopMode,main負責所有主線程事件,例如UI界面的操作,復雜的運算,這樣在同一個runloop中timer就會產(chǎn)生阻塞。

2、模式的改變。主線程的 RunLoop 里有兩個預置的 Mode:kCFRunLoopDefaultMode 和 UITrackingRunLoopMode。

當你創(chuàng)建一個 Timer 并加到 DefaultMode 時,Timer 會得到重復回調(diào),但此時滑動一個ScrollView時,RunLoop 會將 mode 切換為 TrackingRunLoopMode,這時 Timer 就不會被回調(diào),并且也不會影響到滑動操作。所以就會影響到NSTimer不準的情況。

PS:DefaultMode 是 App 平時所處的狀態(tài),rackingRunLoopMode 是追蹤 ScrollView 滑動時的狀態(tài)。

解決的方法,

1、在主線程中進行NSTimer操作,但是將NSTimer實例加到main runloop的特定mode(模式)中。避免被復雜運算操作或者UI界面刷新所干擾。

self.timer = [NSTimer timerWithTimeInterval:1 target:self selector:@selector(showTime) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] addTimer:self.timer forMode:NSRunLoopCommonModes];

2、在子線程中進行NSTimer的操作,再在主線程中修改UI界面顯示操作結(jié)果;

- (void)timerMethod2 {

NSThread *thread = [[NSThread alloc] initWithTarget:self selector:@selector(newThread) object:nil];

[thread start];

}

- (void)newThread

{

@autoreleasepool

{

[NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(showTime) userInfo:nil repeats:YES];

[[NSRunLoop currentRunLoop] run];

}

}

一開始的時候系統(tǒng)就為我們將主線程的main runloop隱式的啟動了。

在創(chuàng)建線程的時候,可以主動獲取當前線程的runloop。每個子線程對應一個runloop

3.GCD定時器不受RunLoop約束,比NSTimer更加準時

@interface ViewController ()

/** 定時器(這里不用帶*,因為dispatch_source_t就是個類,內(nèi)部已經(jīng)包含了*) */

@property (nonatomic, strong) dispatch_source_t timer;

@end

int count = 0;

// 獲得隊列

dispatch_queue_t queue = dispatch_get_main_queue();

// 創(chuàng)建一個定時器(dispatch_source_t本質(zhì)還是個OC對象)

self.timer = dispatch_source_create(DISPATCH_SOURCE_TYPE_TIMER, 0, 0, queue);

// 設置定時器的各種屬性(幾時開始任務,每隔多長時間執(zhí)行一次)

// GCD的時間參數(shù),一般是納秒(1秒 == 10的9次方納秒)

// 何時開始執(zhí)行第一個任務

// dispatch_time(DISPATCH_TIME_NOW, 1.0 * NSEC_PER_SEC) 比當前時間晚3秒

dispatch_time_t start = dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1.0 * NSEC_PER_SEC));

uint64_t interval = (uint64_t)(1.0 * NSEC_PER_SEC);

dispatch_source_set_timer(self.timer, start, interval, 0);

// 設置回調(diào)

dispatch_source_set_event_handler(self.timer, ^{

NSLog(@"------------%@", [NSThread currentThread]);

count++;

if (count == 4) {

// 取消定時器

dispatch_cancel(self.timer);

self.timer = nil;

}

});

// 啟動定時器

dispatch_resume(self.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ā)布平臺,僅提供信息存儲服務。

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

  • ======================= 前言 RunLoop 是 iOS 和 OSX 開發(fā)中非?;A的一個...
    i憬銘閱讀 989評論 0 4
  • runtime 和 runloop 作為一個程序員進階是必須的,也是非常重要的, 在面試過程中是經(jīng)常會被問到的, ...
    made_China閱讀 1,273評論 0 7
  • RunLoop的基本了解 **1 . RunLoop字面的意思 : **運行循環(huán) / 跑圈 **2 . 基本作用 ...
    Mario_ZJ閱讀 594評論 1 3
  • runtime 和 runloop 作為一個程序員進階是必須的,也是非常重要的, 在面試過程中是經(jīng)常會被問到的, ...
    SOI閱讀 22,025評論 3 63
  • 從明天開始, 我要與書為伴, 假裝成有知識的樣子, 縱看歷史, 橫觀世界, 要在書里, 找到屬于我自己的美顏秘籍 ...
    鄭雪峰閱讀 397評論 0 0

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