问题
I have an application with a countdown timer. I've made it with a label that is updated with a function called from a timer this way:
...
int timeCount = 300; // Time in seconds
...
NSTimer *myTimer = [NSTimer scheduledTimerWithTimeInterval:1 target:self selector:@selector(actualizarTiempo:) userInfo:nil repeats:YES];
...
- (void)actualizaTiempo:(NSTimer *)timer {
timeCount -= 1;
if (timeCount <= 0) {
[timer invalidate];
} else {
[labelTime setText:[self formatTime:timeCount]];
}
}
Note: formatTime is a function which receive an integer (number of seconds) and returns a NSString with format mm:ss
Everything works ok, that is, the time counts down but the problem is that I have a UITableView in the application and if I touch the table and drag it (to move along the cells) the timer stops until I release my finger from the screen...
Is this behavior normal? If it is, is there any way to avoid it and make the timer work while dragging the table?
回答1:
By using scheduledTimerWithTimeInterval:
, as j.tom.schroeder says, your timer is automatically schedule on the main run loop for the default modes. This will prevent your timer from firing when your run loop is in a non-default mode, e.g., when tapping or swiping.
The solution, though, is not using a thread, but scheduling your timer for all common modes:
NSTimer *timer = [NSTimer timerWithTimeInterval:1
target:self
selector:@selector(actualizarTiempo:)
userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];
Depending on the kind of events you would like to allow without them stopping your timers, you might also consider UITrackingRunLoopMode
. For more info about run loop modes, see Apple Docs.
回答2:
Heres the Swift version:
Swift 2
var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "removeFromSuperview", userInfo: nil, repeats: false)
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)
Swift 3, 4, 5
var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(removeFromSuperview), userInfo: nil, repeats: false)
RunLoop.main.add(timer, forMode: RunLoop.Mode.common)
回答3:
This is normal behavior. scheduledTimerWithTimeInterval:
schedules on the current run loop, so any interaction with the UITableView will block the actualizarTiempo:
method from being called. Use the NSThread methods detachNewThreadSelector:toTarget:withObject
and sleepForTimeInterval
to perform actualizarTiempo:
on a separate thread.
回答4:
Swift version 4+:
var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.TimerController), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)
if you want to repeat for example as a counter then set repeat = true else = false
来源:https://stackoverflow.com/questions/11712546/nstimer-not-working-while-dragging-a-uitableview