In Stacks, Grids, and Outlines in SwiftUI, a recommendation is made to only use lazy stacks when you encounter performance bottlenecks.
To quote the session, starting at 4:43:
To quote the session, starting at 4:43:
Are there negatives, performance or otherwise, to just always use lazy stacks? I'd like to understand why I shouldn't reach for LazyVStack and LazyHStack first. I understand from the example that using a lazy stack wouldn't confer any benefits, but would we incur any negatives?On the other hand, making the stacks within a given hero view lazy doesn't actually confer any benefits. The content is all visible at once, as soon as the view lands on screen. So everything has to be loaded at once, regardless of the container's default behavior.
If you aren't sure which stack to use, use VStack or HStack. Adopt lazy stacks as a way to resolve performance bottlenecks that you find after profiling with Instruments.
Lazy stacks incur a small amount of extra overhead, both in time and memory, to handle the bookkeeping for what views have and have not been instantiated. In cases where all the views have to be instantiated anyway, that overhead is pure cost with no benefit.
It’s also worth noting that all the views in a lazy stack must be instantiated in some situations that might be unexpected at first glance. For example consider a vertically scrolling ScrollView containing a LazyVStack. So far, so good. But now suppose that LazyVStack includes horizontally scrolling ScrollViews within it—think rows with photo thumbnails. In the general case, all the views in the horizontally scrolling ScrollView have to be instantiated eagerly so that SwiftUI can determine the height of the row.
These unexpected cases are the reason to prefer regular stacks and switch to lazy stacks when it makes a measurable difference. If lazy stacks were always the right answer, SwiftUI could have just made all stacks lazy.
Practically, if the highest level ScrollView in a view hierarchy directly wraps an HStack or VStack, then that’s a good candidate for a lazy stack. Beyond that, profile first lest you accidentally make your app slower while trying to make it faster.
It’s also worth noting that all the views in a lazy stack must be instantiated in some situations that might be unexpected at first glance. For example consider a vertically scrolling ScrollView containing a LazyVStack. So far, so good. But now suppose that LazyVStack includes horizontally scrolling ScrollViews within it—think rows with photo thumbnails. In the general case, all the views in the horizontally scrolling ScrollView have to be instantiated eagerly so that SwiftUI can determine the height of the row.
These unexpected cases are the reason to prefer regular stacks and switch to lazy stacks when it makes a measurable difference. If lazy stacks were always the right answer, SwiftUI could have just made all stacks lazy.
Practically, if the highest level ScrollView in a view hierarchy directly wraps an HStack or VStack, then that’s a good candidate for a lazy stack. Beyond that, profile first lest you accidentally make your app slower while trying to make it faster.