1

I've been following a youtube tutorial for using LazyVStacks. https://www.youtube.com/watch?v=o6D7mUXjSmI

When I run the same code as per the tutorial, the LazyVStack using Xcode Version 13.2.1 (13C100) on a iPhone 11 Pro Max (running iOS 15.2) prints out 83 statements, when only 42 rows are in view. As per the tutorial it should only print 42 statements to the console.

Is this an Xcode/iOS bug? I'm unable to download the latest Xcode as my Mac doesn't support macOS 12.0 to verify.

Video tutorial showing on 42 print statements in the console on iPhone 11 Pro Max: Video tutorial showing on 42 print statements in the console on iPhone 11 Pro Max

My code showing 83 print statements in the console on iPhone 11 Pro Max My code showing 83 print statements in the console on iPhone 11 Pro Max

import SwiftUI

struct SampleRow: View {
    let id: Int

    var body: some View {
        Text("Row \(id)")
    }
    
    init(id: Int) {
        print("Loading row \(id)")
        self.id = id
    }
}

struct ContentView: View {
    var body: some View {
        ScrollView {
            LazyVStack {
                ForEach(1...1000, id: \.self, content: SampleRow.init)
            }
        }
    }
}
Vaz
  • 309
  • 2
  • 15
  • `LazyVStacks` will instantiate the number of views the OS thinks it may need based on a number of factors. This is part of the reason that you can't use `.onAppear()` to determine if a view is actually on screen. There is always a balance, that we don't control, between usage of resources and fluidity of scrolling. In other words, this is not a surprising result. – Yrb Apr 09 '22 at 15:05
  • This goes against the purpose of the LazyVStack and the Apple documentation which states "The stack is “lazy,” in that the stack view doesn’t create items until it needs to render them onscreen. https://developer.apple.com/documentation/swiftui/lazyvstack – Vaz Apr 11 '22 at 11:31
  • Agreed, but the definition of "needs to render them" is creation prior to rendering on screen so they can have a smooth scroll. The faster the scrolling, the further ahead the OS will get. If it is not lazy, it simply instantiates all of them. – Yrb Apr 11 '22 at 14:01
  • So why does the tutorial show 42 print statements, but mine shows 83, for the same code and same device? The behaviour seems inconsistent and I don’t understand why. – Vaz Apr 11 '22 at 16:39
  • Because it depends upon many factors, including the type of devices. Also, are you using the exact same versions of Xcode and the operating system? You should not get hung up on things you cannot control. This is controlled by the OS, and there is nothing we as developers can do to alter it. You have 83 out of 1000. That is lazy instantiation. – Yrb Apr 11 '22 at 16:47
  • Have you actually ran my code above to see what happens for you? How many print statements do you get? – Vaz Apr 13 '22 at 10:07
  • For my setup, 35, which is exactly how many are on the screen. You need to stop obsessing over this. There is nothing wrong with the code; it is the OS that determines this. – Yrb Apr 13 '22 at 14:38

2 Answers2

1

I got the exact same problem, I've got several views that render and fetch data dynamically upon reaching the bottom of the page but for some unknown reason, the same exact code is not working on a view where all the data are rendered at once.. I don't know if it's a bug in LazyVStack implementation or anything else but the behavior is ambiguous

Manfredi6
  • 27
  • 4
0

It's working fine in Xcode 13. I'm not sure why you need a LazyVStack, unless you're using some sort of grid. I slightly modified the code based on there's no much use for it here. It's printing all 1000.

print

enter image description here

import SwiftUI

struct SampleRow: View {
    let id: Int

    var body: some View {
        Text("Row \(id)")
    }
    

    init(id: Int) {
        print("Loading row \(id)")
        self.id = id
    }
}

struct ContentView: View {
    var body: some View {
        ScrollView {
            ForEach(1...1000, id: \.self) { index in
                SampleRow(id: index)
            }
        }
    }
}
cole
  • 1,039
  • 1
  • 8
  • 35
  • 1
    Regardless of whether the LazyVStack is needed here, it doesn't seem to be doing what it has been designed to as per the Apple documentation which states "The stack is “lazy,” in that the stack view doesn’t create items until it needs to render them onscreen." The comparison of what the tutorial shows vs what I get shows this doesn't it? https://developer.apple.com/documentation/swiftui/lazyvstack – Vaz Apr 11 '22 at 11:32
  • I don’t understand the question then? What’s the end goal? – cole Apr 11 '22 at 12:32
  • For the same code in the tutorial, run on the same simulator device, why do I get 83 print statements printed to the console vs 42 print statements in the tutorial – Vaz Apr 11 '22 at 16:41
  • Maybe the tutorial is outdated. Have you tried the code sample. I adjusted the code slightly. – cole Apr 11 '22 at 17:16
  • Have you actually ran my code above to see what happens for you? How many print statements do you get? – Vaz Apr 13 '22 at 10:07
  • @Vaz yes I did, it worked on my end and was printing the statements. Maybe just the Xcode version you’re using. – cole Apr 13 '22 at 15:34