Sometimes in the project we had a problem with NSTimer stopping when we swiped the page. Such as when sliding, write their own countdown stop or the timing of the banner rolling stop.
The problem is that the mode type in the RunLoop is not set to the correct mode type. Starting an NSTimer essentially registers a new event source in the current runloop, and the current MainRunLoop is in UITrackingRunLoopMode when the scrollView is rolled. NSDefaultRunLoopMode messages will not be processed (because the RunLoopMode is different). To accept messages from other Runloops while scrollView is scrolling, we need to change the RunLoopMode between the two.
[[NSRunLoop currentRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
Copy the code
The main RunLoop has two preset modes: kCFRunLoopDefaultMode and UITrackingRunLoopMode. Both modes have been marked with the “Common” attribute. DefaultMode is the normal state of App, TrackingRunLoopMode is to track the state of ScrollView sliding. When you create a Timer and add DefaultMode, the Timer gets repeated callbacks, but when you slide a TableView, RunLoop switches mode to TrackingRunLoopMode, and the Timer doesn’t get called back. And it doesn’t affect the sliding operation.
You need a Timer to get callbacks in both modes. One way to do this is to add the Timer to both modes. Another option is to add the Timer to the top RunLoop’s “commonModeItems.” CommonModeItems is automatically updated by RunLoop to all modes with the Common property.
CommonModes
A Mode can mark itself as a “Common” attribute (by adding its ModeName to RunLoop’s “commonModes”). Whenever the contents of the RunLoop change, the RunLoop automatically synchronizes the Source/Observer/Timer in _commonModeItems to all modes with the “Common” flag.