Обновление UILabel останавливается во время прокрутки UIScrollView - PullRequest
31 голосов
/ 21 марта 2011

У меня есть scrollView с изображением внутри него. scrollView является подвидом superView, а imageView является подвидом 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];
}

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

Ответы [ 5 ]

72 голосов
/ 22 марта 2011

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

Короче говоря: пока прокручивается ваш 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];

(код приходитиз поста, указанного выше).

5 голосов
/ 27 февраля 2018

решение Sergio в Swift 4:

timer = Timer(timeInterval: 1, repeats: true) { [weak self] _ in
    self?.updateTimeLabel()
}
RunLoop.current.add(timer, forMode: .commonModes)
3 голосов
/ 16 марта 2016

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

self.updateTimer = NSTimer.scheduledTimerWithTimeInterval(1.0, target: self, selector: "updateFunction", userInfo: nil, repeats: true)
NSRunLoop.currentRunLoop().addTimer(self.updateTimer, forMode: NSRunLoopCommonModes)
1 голос
/ 19 августа 2017

решение 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)
1 голос
/ 21 марта 2011

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

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

...