NSTimer не работает при перетаскивании UITableView

У меня есть приложение с таймером обратного отсчета. Я сделал это с меткой, которая обновляется с помощью функции, вызванной таймером следующим образом:

...
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]];
    }
}

Примечание: formatTime - это функция, которая получает целое число (количество секунд) и возвращает NSString в формате mm: ss

Все работает нормально, т.е. время отсчитывается, но проблема в том, что у меня есть UITableView в приложении, и если я касаюсь таблицы и перетаскиваю ее (чтобы перемещаться по ячейкам), таймер останавливается, пока я не отпущу палец с экрана...

Это нормальное поведение? Если это так, есть ли способ избежать этого и заставить таймер работать при перетаскивании таблицы?

Ответы

Ответ 1

Используя scheduledTimerWithTimeInterval:, как говорит j.tom.schroeder, ваш таймер автоматически назначает цикл основного запуска для режимов по умолчанию. Это предотвратит запуск вашего таймера, когда ваш цикл запуска находится в режиме не по умолчанию, например, при нажатии или прокрутке.

Решение, однако, не использует поток, но планирование вашего таймера для всех общих режимов:

NSTimer *timer = [NSTimer timerWithTimeInterval:1
                                         target:self
                                       selector:@selector(actualizarTiempo:)
                                       userInfo:nil repeats:YES];
[[NSRunLoop mainRunLoop] addTimer:timer forMode:NSRunLoopCommonModes];

В зависимости от вида событий, которые вы хотели бы разрешить без остановки своих таймеров, вы также можете рассмотреть UITrackingRunLoopMode. Дополнительные сведения о режимах цикла запуска см. В Apple Docs.

Ответ 2

Вот версия Swift:

Swift 2

var timer = NSTimer.scheduledTimerWithTimeInterval(1, target: self, selector: "removeFromSuperview", userInfo: nil, repeats: false)
NSRunLoop.mainRunLoop().addTimer(timer, forMode: NSRunLoopCommonModes)

Свифт 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

Это нормальное поведение. scheduledTimerWithTimeInterval: в текущем цикле выполнения, поэтому любое взаимодействие с UITableView блокирует вызов метода actualizarTiempo:. Используйте методы NSThread detachNewThreadSelector:toTarget:withObject и sleepForTimeInterval для выполнения actualizarTiempo: в отдельном потоке.

Ответ 4

Swift версия 4+:

var timer = Timer.scheduledTimer(timeInterval: 1, target: self, selector: #selector(self.TimerController), userInfo: nil, repeats: true)
RunLoop.main.add(timer, forMode: RunLoopMode.commonModes)

если вы хотите повторить, например, как счетчик, тогда установите repeat = true, иначе = false