[Critical Issue] Content with variable height in a LazyVStack inside a ScrollView causes stuttering / jumping

My goal is to create a chat view in SwiftUI. This requires creating a ScrollView with content of varying heights .

After extensive debugging, I've determined that if you have views within a LazyVStack inside of a ScrollView that do not have a fixed height, it will stutter when you scroll to the top of the view.

––––

PROJECT: Download this project and try for yourself

struct ContentView: View {
  @State var items: [String] = MockData.randomMessages(count: 100)
  
  var body: some View {
    VStack {
      Button("Shuffle items") {
        items = MockData.randomMessages(count: 100)
      }
      ScrollView {
        LazyVStack(spacing: 10) {
          ForEach(Array(items.enumerated()), id: \.offset) { index, item in
            Text(item)
              .background(colors.randomElement()!)
          }
        }
      }
    }
  }
}

My conclusion right now is that LazyVStack only works with child views that have fixed height. This issue alone prevents SwiftUI from being production ready.

Has anyone else tackled this?

works without any problems for me on macos 12.beta, xcode 13.beta, target ios 15 and macCatalyst. Tested on ios15 devices and macos 12. I also tried using 10000, and that works well. Maybe your issue happens on older ios and macos. You maybe interested in "https://stackoverflow.com/questions/68450344/swift-ui-overwhelmed-by-high-frequency-stateobject-updates" where code struggles on ios14 but not ios15.

You could try other ways to see if you can improve the performance, such as:

 ForEach(items.indices, id: \.self) { index in
     Text(items[index]).background(colors.randomElement()!)
 }

or

 ForEach(Array(items.enumerated()), id: \.0) { index, item in
     Text(item).background(colors.randomElement()!)
 }

I had a very similar issue. Not quite the same, but I'll let you know what I did in case it's helpful.

I only had one view in my LazyVStack which had a variable height, and it was at the very top. I put the entire LazyVStack inside another VStack, and moved the one with the variable height to the other VStack. This fixed it because everything inside the LazyVStack then had the same height. For example:

      ScrollView {
        VStack(spacing: 10) {
          VariableHeightView()

          LazyVStack(spacing: 10) {
            ForEach(items) { item in
              FixedHeightView()
            }
          }
        }
      }

You ever figure this out? I'm in the same situation and this is very not fixed on iOS 16.2 / macOS 13.1.

Was this issue fixed? Im still seeing this in iOS 16.4

I have the similar issue after updating to iOS 17.0.1 Previous versions (15.0 and 16.2) were fine.

What worked for me

I have replaced Scrollview and Lazyvstack with a 'List' and it has resolved the stuttering/flickering issue for me.

So for the above example, try to change this code

VStack {
      Button("Shuffle items") {
        items = MockData.randomMessages(count: 100)
      }
      ScrollView {
        LazyVStack(spacing: 10) {
          ForEach(Array(items
......
}

To this:

VStack {
      Button("Shuffle items") {
        items = MockData.randomMessages(count: 100)
      }
      List {
          ForEach(Array(items
......
}

Let me know if it solved your problem.

Thanks

It looks like this has been resolved in iOS 17.4. Not sure which release fixed it, but I just tested it on my device with iOS 17.4 and am not seeing the stutter anymore.

[Critical Issue] Content with variable height in a LazyVStack inside a ScrollView causes stuttering / jumping
 
 
Q