NSTimer導致誤差的原因:
1委粉、NSTimer加在main runloop中簇搅,模式是NSDefaultRunLoopMode凡泣,main負責所有主線程事件,例如UI界面的操作润讥,復雜的運算,這樣在同一個runloop中timer就會產生阻塞伙判。
2象对、模式的改變。主線程的 RunLoop 里有兩個預置的 Mode:kCFRunLoopDefaultMode 和 UITrackingRunLoopMode宴抚。
當你創(chuàng)建一個 Timer 并加到 DefaultMode 時勒魔,Timer 會得到重復回調,但此時滑動一個ScrollView時菇曲,RunLoop 會將 mode 切換為 TrackingRunLoopMode冠绢,這時 Timer 就不會被回調,并且也不會影響到滑動操作常潮。所以就會影響到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界面顯示操作結果;
- (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