【问题标题】:UILabel updating stops during scrolling UIScrollView滚动 UIScrollView 期间 UILabel 更新停止
【发布时间】:2011-07-19 16:09:29
【问题描述】:

我有一个滚动视图,里面有一个 imageView。 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];
}

感谢您的帮助。

【问题讨论】:

    标签: iphone objective-c ios uiviewcontroller uiscrollview


    【解决方案1】:

    我最近遇到了同样的问题,在这里找到了解决方案: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];
    

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

    【讨论】:

    • 感谢您提供简单的解决方案。
    • 在他使用 timerWithTimeInterval:target:selector:userInfo:repeats 时你使用 scheduleTimerWithTimeInterval:target:selector:userInfo:repeats 有什么原因吗?
    • 我使用了与 OP 相同的调用。使用timerWithTimeInterval:target:selector:userInfo:repeats 会更正确,因为无论如何我们都要将计时器添加到运行循环中,所以不需要scheduled 版本的调用。
    • 这就是滚动时没有调用我的 NSURLConnection 委托方法的原因;我需要使用 NSURLConnection 的scheduleInRunLoop:forMode: 方法。所以 +1 为我指明了正确的方向。
    【解决方案2】:

    sergio's Swift 5 中的解决方案:

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

    【讨论】:

      【解决方案3】:

      我在滚动 UIScrollView 时看到了类似的行为。可能发生的情况是滚动操作完全阻塞了主运行循环,它负责与视图更新相关的任何事情。您在这里没有做错任何事情,视图层次结构的更新应该由主循环处理,因此您不能只将 UILabel 更新放在后台线程上(尽管我可能仍会尝试看看会发生什么)。

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

      【讨论】:

      • 谢谢帕斯卡。我从来没有尝试过使用不同的线程。我会读一些东西,我会试一试。
      • 目前我试图将更新的值传递给实例类变量。使用 scrollViewDidScroll 委托方法来更新标签(在滚动操作期间)不能解决这个问题。 “呜呜!”
      • 是的,我担心会是这样。滚动和滚动的流畅性对于 iPhone 体验至关重要,从用户的角度来看,所有的力量都用于动画是有道理的,这至少可以解释一下。
      • 无论如何...我们可以使用与滚动视图的 contentOffset 属性相关的任何任务。我认为 iOS 应该着眼于支持不受 UIScrollViewDelegate 协议限制的同步任务。
      【解决方案4】:

      sergio's Swift 2 中的解决方案:

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

      【讨论】:

        【解决方案5】:

        sergio's 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)
        

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2013-09-29
          • 1970-01-01
          • 1970-01-01
          • 2023-04-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多