在滚动UIScrollView期间,UILabel更新停止

时间:2011-03-21 13:00:42

标签: iphone objective-c ios uiviewcontroller uiscrollview

我有一个带有imageView的scrollView。 scrollView是superView的子视图,imageView是scrollView的子视图。 我还有一个标签(在超级视图级别),每隔毫秒从NSTimer接收其text属性的更新值。

问题是: 在滚动期间,标签停止显示更新。滚动结束时,标签上的更新将重新开始。更新重启时,它们是正确的;这意味着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 个答案:

答案 0 :(得分:72)

我最近遇到了同样的问题,并在此处找到了解决方案:My custom UI elements...

简而言之:当您的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];

(代码来自上面链接的帖子。)

答案 1 :(得分:4)

Swift 4中的

sergio's解决方案:

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

答案 2 :(得分:3)

Swift 2中的

sergio's解决方案:

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

答案 3 :(得分:1)

我在滚动UIScrollView的过程中看到了类似的行为。可能发生的是滚动操作完全阻止主运行循环,它负责与视图更新相关的任何事情。你没有在这里做错任何事情,视图层次结构的更新应该由主循环处理,所以你不能只是把你的UILabel更新放在后台线程上(虽然我可能仍然会尝试看看会发生什么)。 / p>

我还没有真正研究过这个问题,但我认为你几乎无能为力。我很乐意接受证明我错的答案!

答案 4 :(得分:1)

Swift 3.x中的

sergio's解决方案:

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