ProgressView inside SwiftUI List disappearing after list is updated

1.1k views Asked by At

The circular (default) SwiftUI ProgressView disappears within a List whenever the list gets expanded with new content because of a .onAppear modifier on the ProgressView. 

The ProgressView becomes invisible, although its allocated cell (and its label, if assigned) within the list remain visible.

I want to keep the ProgressView at the bottom of the list so that the list gets automatically updated with new content being downloaded from the server when the user reaches the end of the list.

Possible duplicate of this article but the accepted answer does not tackle the reason why the view disappears.

Reprex:

struct ContentView: View {
    
    @State var items: [String] = ["Item 1", "Item 2", "Item 3", "Item 4", "Item 5", "Item 6"]
        
    var body: some View {
        List {
            ForEach(items, id: \.self) { item in
                Text(item)
                    .frame(height: 100)
            }
            
            ProgressView {
                Text("Loading")
            }
            .frame(maxWidth: .greatestFiniteMagnitude, alignment: .center)
            .onAppear(perform: endOfListReached)
        }
    }
    
    func endOfListReached() {
        DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
            items.append("Item \(items.count + 1)")
        }
    }
}
2

There are 2 answers

4
Thofreym On BEST ANSWER

I would rather keep the List for its convenient layout, but it appears that the List is causing the issue here and that changing it to a ScrollView and LazyVStack and styling it with Dividers works as expected.

0
turtleisaac On

I believe had this same issue with the ProgressView disappearing, and what I ended up doing to solve it was to make a @State var showProgressView: Bool and setting it to true on the onAppear of the view, and false on the onDisappear. Put the ProgressView within an if statement that checks the boolean and that should make the ProgressView persist even when the content it is within unloads then reloads.