NSTimerタイマがScrollViewスライド時に無効になるソリューション

2030 ワード

私たちはよくこのような状況に遭遇します.tableviewの上にタイミングのNSTimerがあり、tableView(scrollView)がスライドするとNSTimerは失効します.
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のもう一つのモードであり、その作用はNSDefaultRunLoopModeUITrackingRunLoopModeの結合に等価であり、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];
}