繁体   English   中英

SwiftUI:将 LazyVStack 或 LazyHStack 放入 ScrollView 会导致卡顿(Apple 错误??)

[英]SwiftUI: Putting a LazyVStack or LazyHStack in a ScrollView causes stuttering (Apple bug??)

XCode 版本 12.4 (12D4e)

每次在 ScrollView 中实现 Lazy 堆栈时,我都会遇到这个问题:

  1. LazyHStack添加到水平ScrollView或将LazyVStack到垂直ScrollView
  2. 添加足够的内容,使滚动视图的内容大小超过其边界

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

预期行为:滚动视图停留在您的手指下时,它的行为符合预期

观察到的行为:它结巴和跳跃

场景 2 - 快速滚动到边缘,因此它必须反弹

预期行为:平稳反弹

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

我的理论我的理论是,由于使用了惰性堆栈,当视图离开屏幕时,它会从视图层次结构中删除,从而造成卡顿。

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

示例代码

        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 视图才能工作。

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

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

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

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

这是重现问题的 MWE:

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

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

稍微减小宽度会使结巴 go 消失:

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 上进行了测试。对于这个特定的示例,问题仅发生在设备上(可能是因为我在模拟器上滚动速度不够快)。 但是我在模拟器上更复杂的视图上也遇到了这个问题。

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

UIScrollView.appearance().bounces = false

我添加了一个清晰的矩形

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

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

我有一个非常相似的问题,禁用edgesForExtendedLayout对我有用。

如果 SwiftUI 视图在 UIHostingController 中使用,您可以尝试将以下内容添加到UIHostingController子类:

class MyViewController: UIHostingController<MyView> {

  init() {
        let view = MyView()
        super.init(rootView: view)
  }

  override func viewDidLoad() {
      super.viewDidLoad()
      edgesForExtendedLayout = []
  }

这在 xcode 13.2.1 和 iOS 15.2 下是可重现的

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM