【问题标题】:SwiftUI: Putting a LazyVStack or LazyHStack in a ScrollView causes stuttering (Apple bug??)SwiftUI:将 LazyVStack 或 LazyHStack 放入 ScrollView 会导致卡顿(Apple 错误??)
【发布时间】:2021-06-05 23:28:36
【问题描述】:

XCode 版本 12.4 (12D4e)

每次我在 ScrollView 中实现延迟堆栈时都会遇到这种情况:

  1. LazyHStack 添加到水平ScrollView 或将LazyVStack 添加到垂直ScrollView
  2. 添加足够的内容以使滚动视图的内容大小超出其范围

场景 1 - 将滚动视图拉出边界(就像拉动刷新一样)

预期行为:当滚动视图停留在您的手指下时,它的行为与预期一样

观察到的行为:它口吃和跳跃

场景 2 - 快速滚动到边缘,使其必须反弹

预期行为:它平稳地弹跳

观察到的行为:它在到达边缘时停止并抖动,但不反弹

我的理论 我的理论是,由于使用了延迟堆栈,当视图离开屏幕时,它会从视图层次结构中移除,从而产生卡顿。

我想知道有没有其他人遇到过这种情况?这是 SwiftUI 中的错误吗?几个月来,我已经在不同的项目中可靠地复制了这一点,最终不使用我希望可以的 Lazy 堆栈。

示例代码

        ScrollView {
          LazyVStack {
            ForEach(viewModel.items) { items in
              SomeView(viewModel: .init(context: viewModel.context, item: item))
            }
          }

注意:卡顿只发生在滚动视图的顶部

** 2021 年 7 月 10 日更新 **

iOS 15 版本 13.0 beta (13A5155e) 中仍然存在这种情况。

在下面的视频中,请注意滚动条的行为以及我们到达底部时的卡顿:

https://youtu.be/z2pybl5yYqk

** 2021 年 7 月 19 日更新 **

我把视图中的所有内容都撕掉了,然后一个一个地建立起来——当我在一个简单的Text 元素周围放置一个VStack/HStack/ZStack 时,LazyVStack 就会开始卡顿。

如果我将fixedSize(horizontal: false, vertical: true) 添加到Text 元素,它似乎停止了口吃。只要我添加一个高度可变的UIViewRepresentable,它就会再次开始卡顿。

似乎在 LazyStack 中,每个孩子都需要某种固定大小或纯 SwiftUI 视图才能工作。

我会继续挖掘。必须...解决...

【问题讨论】:

  • 你的理论是不正确的,一旦 Lazy Stack 加载了一个视图并且该视图不需要更新,它将保留在内存中,直到对该视图进行新的更新。
  • @swiftPunk 你能链接到任何文档吗?我没有说它是从内存中删除的,我推测它是在屏幕外时从视图层次结构中删除的
  • 我可以确认我也遇到了这个问题。我在反馈中提交了问题,还提交了代码级支持票。有趣的是,我没有收到代码级支持票的回复,这是我以前从未遇到过的。这发生在应用程序的多个区域,因此这是一种糟糕的用户体验。如果我收到回复,我会在这里报告。这是我能够找到的第一篇带有重现步骤和结果的帖子。我将通过电子邮件向 Apple 发送有关代码级支持票的信息。我在上个月报告了这个 11 月、12 月 FB8899884、FB8941709 和 DTS 762092933(没有回复)。
  • 我在 ScrollView 中遇到了与 LazyVStack 完全相同的问题。希望可以解决。你的帖子非常清楚地解释了这个问题,所以谢谢你。这与我切换到列表视图时得到的预期反弹行为非常不同。希望他们尽快为 LazyVStack/HStack 修复它
  • 我现在正在努力解决这个错误。 @TomGODDARD 你有关于这些门票的任何消息吗?我还没有找到工作。

标签: ios swift xcode swiftui swiftui-scrollview


【解决方案1】:

我添加了一个清晰的矩形

ScrollView {
    LazyVStack {
        Rectangle().foregroundColor(.clear).frame(height: 1.0)
        ...
    }
}

它似乎解决了我在 ScrollView 下的 LazyVStack 中遇到的大部分问题。

【讨论】:

    【解决方案2】:

    尝试禁用 ScrollView 反弹。 在 onAppear 或 init 中添加以下行,

    UIScrollView.appearance().bounces = false

    【讨论】:

      【解决方案3】:

      我可以确认在带有 Xcode 13 的 iOS 15 中仍然存在卡顿问题。我不确定是什么原因造成的,但它似乎与 LazyStacks 创建和布局项目的方式有关。

      这是重现问题的 MWE:

      ScrollView(.horizontal) {
          LazyHStack {
              Color.red.frame(width: 450)
              Color.green.frame(width: 250)
              Color.blue.frame(width: 250)
          }
      }
      .frame(width: 350)
      

      在这个例子中,红色的边框看起来“足够宽”,在屏幕前缘弹跳时会导致卡顿。

      稍微减小宽度可以消除口吃:

      ScrollView(.horizontal) {
          LazyHStack {
              Color.red.frame(width: 400)
              Color.green.frame(width: 250)
              Color.blue.frame(width: 250)
          }
      }
      .frame(width: 350)
      

      注意:在带有 Xcode 13 beta 1 和 iOS 15 beta 1 的 iPhone Xs Max 上进行了测试。对于这个特定示例,问题仅发生在设备上(可能是因为我在模拟器上滚动速度不够快)。但我在模拟器上更复杂的视图上也遇到过这个问题。

      【讨论】:

        【解决方案4】:

        我已确认该问题在 iOS 15 中已解决。不确定这是否有帮助,但也使用 Xcode 13 重新编译了该应用程序。?

        【讨论】:

        • 汤姆,谢谢你的帮助!不幸的是,我刚刚在 iOS 15 中重现了这个。我在 ScrollView 中有一个 LazyVStack,当我用大量项目填充它时,它开始结结巴巴。我注意到右侧的滚动条似乎也在改变大小并在我滚动时上下跳跃。暗示正在发生一些奇怪的事情。
        • @chrysb 我想请您使用 Feed 助手报告此问题,就像我之前所做的那样。不幸的是,助手说没有类似的报告,所以如果我们能开始让更多人向苹果报告这个问题,那就太好了。我的反馈标题类似于“使用 LazyStacks 在 ScrollView 上弹跳时出现口吃”。
        • 这肯定还在 iOS 15 和 Xcode 上发生。
        【解决方案5】:

        我收到了 DTS 的回复,他们确认这是一个错误,但没有解决方法。您可以参考我的反馈 ID 并提交反馈项目。我想他们会用新的 swift 版本解决这个问题,因为我认为这可能是一个遗留缺陷,并且可能会导致重大更改。换句话说,它与原生组件和导航栏有关,他们必须打破一些东西来修复它。这意味着 iOS 14 中的 SwiftUI 应用程序可能永远不兼容。但我只是推测。如果我得到任何消息,我会告诉所有人。这确实是一个主要障碍,完全破坏了 IMO 的用户体验。

        【讨论】:

        • 我今天从 Apple 得到了另一个确认,这仍然是一个错误:“在你的 Mac 目标上,这一切正常,但我看到 iOS 上存在滚动问题。这个问题绝对是 iOS 上 SwiftUI 的一个错误。我建议不要重写你的应用程序,而是为你的 UIScrollView 使用 UIViewRepresentable (或者实际上 UITable / UICollection 视图在这里最有意义)。如果你使用可重用的视图,例如表格或集合,这些问题几乎肯定会出现走开。您不需要重写您的应用,但如果此问题阻止发布,您应该添加 UIViewRepresentable。"
        猜你喜欢
        • 1970-01-01
        • 2020-03-03
        • 2017-09-18
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2021-01-11
        相关资源
        最近更新 更多