Подтвердить что ты не робот

NSTimer не срабатывает при блокировке runloop

Я только что закончил с моим приложением, и бета-тестирование обнаружило ошибку в секундомере... Секундомер использует nstimer для подсчета и имеет таблицу для хранения кругов, но когда прокручивается таблица круга, часы останавливаются или приостанавливаются и не компенсируют потерянное время.

Это было остановлено, если:

startingTime = [[NSDate date] timeIntervalSince1970];

чтобы вычислить прошедшее время.

но я все еще использую NSTimer для запуска каждые 0,1 секунды, а это означает, что прокрутка по-прежнему останавливает таймер, хотя прошедшее время будет правильно обновляться в конце... и сравнивая это с секундомером Apple, это делает меня если этот секундомер имеет отдельный поток только для подсчета прошедшего времени. Кто-нибудь знает, как это делается?

Теперь, используя время с тех пор, как Epoch работает в одном смысле, но это усложняет вопрос о запуске, остановке и перезапуске секундомера

когда часы остановлены, время хранится и используется для вычисления смещения, когда часы перезапускаются, но, кажется, появляется некоторая латентность, и время, когда часы снова перезапускаются, заметно ускоряется.

Мы с благодарностью будем оценивать любые мысли о первопричине или решении.

4b9b3361

Ответ 1

Ответ bbum обеспечивает лучший способ разработки вашего приложения, но если вы хотите, чтобы ваш таймер срабатывал независимо от того, манипулирует ли пользователь интерфейсом или нет, вам нужно добавить его в режим отслеживания runloop.

Предполагая, что вы разрабатываете для iPhone, этот режим UITrackingRunLoopMode. Если вы разрабатываете для Mac, есть и так называемый NSEventTrackingRunLoopMode.

NSRunLoop *runloop = [NSRunLoop currentRunLoop];
NSTimer *timer = [NSTimer timerWithTimeInterval:0.1 target:self selector:@selector(myTimerAction:) userInfo:nil repeats:YES];
[runloop addTimer:timer forMode:NSRunLoopCommonModes];
[runloop addTimer:timer forMode:UITrackingRunLoopMode];

Ответ 2

Если цикл событий не запущен, любые таймеры не будут запускаться до тех пор, пока цикл событий не будет запущен снова. Даже если цикл событий не является блоком, таймер не гарантирует, что он срабатывает точно в течение заданного интервала. Если ваши тайминги были полностью основаны на запуске таймеров, количество ошибок будет расти с течением времени.

Вам нужно отслеживать продолжительность отдельно от срабатывания таймеров. Каждый раз, когда срабатывает таймер, пересчитывайте продолжительность и повторно отображайте.

Для типа установки start/pause/restart/stop вы обычно хотите:

  • захватить время при запуске (либо в качестве экземпляра NSDate, либо как значение NSTimeInterval)

  • после паузы или остановки, возьмите время при паузе/остановке. Вычтите время начала с этого времени, и у вас есть продолжительность интервала

  • при перезапуске возьмите время после перезапуска, а также продолжайте уже прошедшую длительность

  • после паузы/остановки, возьмите время при паузе/остановке и добавьте уже прошедшую длительность

В общем, все это с помощью значений NSTimeInterval, которые являются только удвоениями, проще всего. Однако, если вам нужно отслеживать фактический момент времени, когда произошли события, используйте вместо него экземпляры NSDate.