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

Обновление UILabel прекращается во время прокрутки UIScrollView

У меня есть scrollView с изображением внутри. scrollView - это subView супервизора, а imageView - это subView scrollView. У меня также есть метка (на уровне супер-просмотра), которая получает обновленные значения по свойству текста из NSTimer каждые миллисекунды.

Проблема заключается в следующем: Во время прокрутки метка перестает отображать обновления. Когда прокрутка заканчивается, обновления перезапуска метки. При обновлении обновлений они верны; это означает, что значения label.text обновляются так, как ожидалось, но при прокрутке дисплей обновлений иногда переоценивается. Я хотел бы показывать обновления на ярлыке независимо от прокрутки или нет.

Вот как реализованы обновления меток:

- (void)startElapsedTimeTimer {

     [self setStartTime:CFAbsoluteTimeGetCurrent()];
     NSTimer *elapsedTimeTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 target:self selector:@selector(updateElapsedTimeLabel) repeats:YES];
}

- (void)updateElapsedTimeLabel {

    CFTimeInterval currentTime = CFAbsoluteTimeGetCurrent();
    float theTime = currentTime - startTime;

    elapsedTimeLabel.text = [NSString stringWithFormat:@"%1.2f sec.", theTime];
}

Спасибо за любую помощь.

4b9b3361

Ответ 1

У меня была такая же проблема, и я нашел решение здесь: Мои пользовательские элементы пользовательского интерфейса....

Вкратце: пока ваш UIScrollView прокручивается, NSTimer не обновляется, потому что циклы запуска запускаются в другом режиме (NSRunLoopCommonModes, режим, используемый для отслеживания событий).

Решение добавляет ваш таймер к NSRunLoopModes сразу после создания:

NSTimer *elapsedTimeTimer = [NSTimer scheduledTimerWithTimeInterval:0.001 
                                                             target:self 
                                                           selector:@selector(updateElapsedTimeLabel) 
                                                           userInfo:nil 
                                                            repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:elapsedTimeTimer 
                             forMode:NSRunLoopCommonModes];

(Код исходит из сообщения, указанного выше).

Ответ 2

Решение Sergio в Swift 5:

timer = Timer(timeInterval: 1, repeats: true) { [weak self] _ in
    self?.updateTimeLabel()
}
RunLoop.current.add(timer, forMode: .common)

Ответ 3

Решение Sergio в Swift 2:

self.updateTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "updateFunction", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(self.updateTimer, forMode: NSRunLoopCommonModes)

Ответ 4

Я видел подобное поведение в сочетании с прокруткой UIScrollView. Вероятно, происходит то, что действие прокрутки полностью блокирует основной цикл цикла, который отвечает за все, что связано с просмотром обновлений. Вы не делаете ничего плохого, обновления в иерархии представлений должны обрабатываться основным циклом, поэтому вы не можете просто обновлять свой UILabel в фоновом потоке (хотя я, вероятно, все же попробую посмотреть, что произойдет).

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

Ответ 5

Решение Sergio в Swift 3.x:

self.updateTimer = Timer.scheduledTimer(timeInterval:1.0, target: self, selector: "updateFunction", userInfo: nil, repeats: true)
RunLoop.current.add(self.updateTimer, forMode: RunLoopMode.commonModes)