NSTimerタイマがScrollViewスライド時に無効になるソリューション
2030 ワード
私たちはよくこのような状況に遭遇します.tableviewの上にタイミングのNSTimerがあり、tableView(scrollView)がスライドするとNSTimerは失効します.
NSTimerがなぜ失効したのかは、runloopという概念にかかわるので、runloopについて知らない場合は、ibireme大神のこのブログを読んでRunLoopを深く理解してください
通常timerを作成します
あるいは
上記の2つの方法では、タイマTimerを現在のプライマリスレッドに追加し、現在のプライマリスレッドrunloopのmodeは
私たちがscrollviewをスライドしないときはメインスレッドのrunloopは
失効の原因が分かったら、問題を解決するのも簡単で、2つの方法があります.
1つ目:スレッドrunloopのmodeを変更する
2つ目は、タイマをサブスレッドに配置して作成します.
NSTimerがなぜ失効したのかは、runloopという概念にかかわるので、runloopについて知らない場合は、ibireme大神のこのブログを読んでRunLoopを深く理解してください
通常timerを作成します
// timer NSDefaultRunLoopMode
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(startTimer) userInfo:nil repeats:YES];
あるいは
self.timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(startTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode: NSDefaultRunLoopMode];
上記の2つの方法では、タイマTimerを現在のプライマリスレッドに追加し、現在のプライマリスレッドrunloopのmodeは
NSDefaultRunLoopMode
であり、このモードもrunloopのデフォルトモードである.私たちがscrollviewをスライドしないときはメインスレッドのrunloopは
NSDefaultRunLoopMode
モードに留まり、このときタイマTimerは有効ですが、scrollviewをスライドするとメインスレッドのrunloopはUITrackingRunLoopMode
モードに切り替わります.このときタイマTimerはNSDefaultRunLoopMode
モードなのでメインスレッドのrunloopはタイマを処理できず、タイマも当然失効し、スライドを停止すると、runloopのモードはNSDefaultRunLoopMode
に戻り、タイマが再有効になります.失効の原因が分かったら、問題を解決するのも簡単で、2つの方法があります.
1つ目:スレッドrunloopのmodeを変更する
self.timer = [NSTimer timerWithTimeInterval:1.0f target:self selector:@selector(startTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.timer forMode: NSRunLoopCommonModes];
NSRunLoopCommonModes
はrunloopのもう一つのモードであり、その作用はNSDefaultRunLoopMode
とUITrackingRunLoopMode
の結合に等価であり、scrollviewをスライドするときはUITrackingRunLoopMode
に等価であり、スライドを停止するときはUITrackingRunLoopMode
に等価である.2つ目は、タイマをサブスレッドに配置して作成します.
//
[NSThread detachNewThreadSelector:@selector(createTimer) toTarget:self withObject:nil];
//
- (void)createTimer {
self.timer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:@selector(startTimer) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] run];
}