xcodeswiftuipagination

Progress View doesn't show on second + load when trying to do pagination SwiftUI


Progress View doesn't show on second + load when trying to do pagination. When I scroll to the bottom the progress view will appear once. But all the other times it doesn't. This only seems to occur when im using some sort of animation.

If I just have a static text like "Loading..." it works as expected. I added the section group where it checks a condition to verify if it should be presented or not. Not sure if I'm supposed to use something like "stop animating" like the loading indicator has in UIKit

enter image description here

struct ContentView: View {
    @State var movies: [Movie] = []
    @State var currentPage = 1
    @State private var isLoading = false
    
    var body: some View {
        NavigationView {
            List {
                Section {
                    
                } header: {
                    Text("Top Movies")
                }
                
                ForEach(movies) { movie in
                    HStack(spacing: 8) {
                        AsyncImage(url: movie.posterURL, scale: 5) { image in
                            image
                                .resizable()
                                .aspectRatio(contentMode: .fit)
                                .frame(width: 100)
                                .cornerRadius(10)
                        } placeholder: {
                            ProgressView()
                                .frame(width: 100)
                        }
                        
                        VStack(alignment: .leading, spacing: 10) {
                            Text(movie.title)
                                .font(.headline)
                            Text(movie.overview)
                                .lineLimit(5)
                                .font(.subheadline)
                            Spacer()
                        }
                        .padding(.top, 10)
                    }
                    .onAppear {
                        Task {
                            //Implementing infinite scroll
                            if movie == movies.last {
                                isLoading = true
                                currentPage += 1
                                movies += await loadMovies(page: currentPage)
                                isLoading = false
                            }
                        }
                    }
                }
                
                Section {
                    
                } footer: {
                    if isLoading {
                        HStack {
                            Spacer()
                            ProgressView()
                                .tint(.green)
                            Spacer()
                        }
                    } else {
                        EmptyView()
                    }
                }
            }
            .navigationTitle("Movies")
            .navigationBarTitleDisplayMode(.inline)
            .listStyle(.grouped)
            .task {
                movies = await loadMovies()
            }
            .refreshable {
                movies = await loadMovies()
            }
        }
    }
}

even when I look at the view hierarchy its like the progress view square is there but the icon / loading indicator isn't showing: enter image description here

If I add the overlay modifier it works but I don't like doing this because when I scroll back up before the content finishes loading the spinner is above the list view:?

    .overlay(alignment: .bottom, content: {
        if isLoading {
            HStack {
                Spacer()
                ProgressView()
                    .tint(.green)
                Spacer()
            }
        } else {
            EmptyView()
        }
    })

Solution

  • We also had this problem, we think it is a bug of ProgressView. Our temporary correction is to identify the ProgressView with a unique id in order to render it again.

    struct ContentView: View {
        @State var id = 0
    
        var body: some View {
            ProgressView()
                .id(id)
                .onAppear {
                    ...
                    id += 1
                }
        }
    }