【问题标题】:UIScrollView contentOffset not updating when changedUIScrollView contentOffset 更改时不更新
【发布时间】:2018-04-11 10:30:17
【问题描述】:

看到一个关于更改滚动视图的内容偏移属性的奇怪问题。

我有一个 CADisplayLink 每帧调用一个方法。此方法计算调整内容偏移量以产生自动滚动类型的效果。

@objc private func tick() {

    let fps = 1 / (displayLink.targetTimestamp - displayLink.timestamp)

    let relativeAutoscrollAmount = autoscrollAmount / CGFloat(fps)

    scrollView.contentOffset.x += relativeAutoscrollAmount
}

autoscrollAmount 是一个CGFloat 属性,表示每秒移动多少像素。在像 iPhone 这样的 60Hz 屏幕上,如果该属性为 5,这意味着每次调用该方法都会发生 5/60 的偏移。但是,内容偏移量实际上从未改变!无论是视觉上还是记忆中,我都可以随时打破和检查它,它总是为 0!

请注意,如果我每次将其调整 1 或更大,它就可以正常工作。不过,动画还远远不够快。

有什么想法吗?

编辑: 显然,您实际上一次不能调整少于一个像素,但是当我之前使用约束常数执行此操作时,系统只是计算了如何处理此问题。 (我假设每隔几个刻度移动一次)。

【问题讨论】:

    标签: ios swift uiscrollview cadisplaylink


    【解决方案1】:

    我相信我有答案,或者至少,我有一个基于一些很好证据支持的理论的解释。来了……

    在问题中,我提供了 5/60 的示例,其中 5 是每秒移动的像素数量,60 是我屏幕的刷新率。这大约为 0.083,正如我所说,这导致 contentOffset 没有更新。

    此时,我假设最小值为 1(因为您无法更改半个像素),但实际上并非如此。我开始尝试不同的十进制值,希望找到停止对contentOffset 进行更新的阈值。

    经过多次反复试验,我发现了这个价值。它是 0.167。在我看来,这绝对没有任何意义。但显然必须有什么东西,所以我开始以各种方式操纵它,试图观察某种模式。

    很快就清楚0.167 * 6 == 1,虽然是一个有趣的观察,但又似乎没有什么意义。直到您注意到我正在测试的 iPhone X 上的显示屏刷新率为 60Hz10 乘以 6。在这一点上,我仍然在黑暗中盲目地刺伤,但这至少是我可以探索的线索。

    据此,我推测系统每 6 毫秒评估一次图层位置的变化,或者更实际地,每个显示周期评估 10 次。这支持了我所看到的行为,如果移动值传递太小(即它不能以每个显示周期理论的 10 次表示),它被简单地忽略了。

    这是一个相当大胆的推测,所以我决定看看我是否可以收集证据来支持这个理论。我启动了具有 120Hz 显示屏(而不是 iPhone X 上的 60Hz 显示屏)的 iPad Pro,看看是否有趋势。果然,有。现在看到运动的最小值是 60Hz 屏幕上的一半。考虑到更高的刷新率(实际上是两倍),以及每个屏幕周期 10 次更新的原始假设,我现在看到每个屏幕周期有 20 次更新,每 6 毫秒,和以前一样。这里肯定有关系。

    现在我想强调,这完全是猜测,但至少我今晚可以入睡,知道为什么会发生这种情况!我也很想听听其他人的想法。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2011-03-15
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-02-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多