List and LazyVStack performance and reusability – Swiftui

by
Alexei Petrov
swiftui-ontapgesture

Quick Fix: Utilize List’s built-in view reuse mechanism for better performance and memory efficiency when dealing with large datasets.

The Problem:

A developer is benchmarking the performance of List, ScrollView, and LazyVStack in SwiftUI. They have observed that Case 2, where ForEach wraps LazyVStack, outperforms Case 1, where LazyVStack wraps ForEach. Their expectation was that Case 1 would be more efficient. In Case 1, images are not unloaded from memory as the user scrolls, leading to increased memory usage. Case 2, however, unloads images from memory during scrolling. The developer is perplexed by this behavior and seeks an explanation for why Case 2 performs better and whether it creates a new LazyVStack for each row.

The Solutions:

Solution 1: List’s reuse mechanism

List lazily loads views, but also has a view re-use mechanism. LazyVStack lazy loads views, but doesn’t have a re-use mechanism, so it will keep everything as it grows.

Case 1:

In this case, there is only one LazyVStack inside the List. The LazyVStack starts off small and keeps growing as you scroll, but the List is unaware of this because it only contains a single view.

Case 2:

The List knows how to deal with a ForEach and can reuse the views as you scroll. You’re creating a new (pointless) LazyVStack for each row, but it isn’t really doing anything since it only ever contains a single view.

Case 4:

If you have a collection of identifiable types and you want a list of them, you don’t even need a ForEach. You can just write it as a List containing the async image.

In this case, the List will lazy load the views and reuse them as you scroll, without the need for a LazyVStack.

Q&A

Why does case 2 perform better than case 1?

List lazy loads views and reuses them, while LazyVStack doesn’t, causing case 1 to keep growing in memory.

What can be done to improve performance in case 1?

Use a List with a ForEach inside it, as in case 2, to take advantage of List’s reuse mechanism.

Is there a simpler way to achieve the same result?

If you have a collection of identifiable types and don’t need dynamic actions, you can use a simple List without a ForEach or LazyVStack.

Video Explanation:

The following video, titled "SwiftUI List Performance - YouTube", provides additional insights and in-depth exploration related to the topics discussed in this post.

Play video

When it comes to displaying lists of items in iOS apps, developers have two main options: the SwiftUI List view and the UIKit ...