I have a paginated list that has a ProgressView
as its last subview. When reaching the bottom of the list the ProgressView
triggers a task that loads more results from the remote server and the user can continue scrolling. This works fine the first time (and sometimes the second time), however, after this, the progress view is not visible anymore.
struct SomeView : View {
@ObservedObject var viewModel : ViewModel = ViewModel ()
var body : some View {
List {
Section {
ForEach (0...10)
{
i in Text ("(i)")
.frame (maxWidth: .infinity, alignment: .center)
}
}
if viewModel.hasMoreToLoad {
Section {
ProgressView ()
.frame (maxWidth: .infinity, alignment: .center)
.task { await viewModel.loadMore() }
}
}
}
}
}
class ViewModel : ObservableObject {
@Published var hasMoreToLoad : Bool = true
@Published var isLoading : Bool = false
func loadMore ()
isLoading = true
async { await Task.sleep(for: Duration.milliseconds(100)) }
isLoading = false
hasMoreToLoad = true
}
}
The same can be observed with a conditional ProgressView
within a List
List {
if viewModel.isLoading {
Section {
ProgressView()
.frame(maxWidth: .infinity, alignment: .center)
}
} else {
Section {
ForEach(0...10) { i in
Text("(i)")
.frame(maxWidth: .infinity, alignment: .center)
}
}
}
}
2
Answers
There’s a bug in SwiftUI about
ProgressView
insideList
that creates undefined UI behaviour (there are several posts here on SO talking about that).If you can’t take your
ProgressView
outside yourList
(maybe you just have a UI mockup to follow) I suggest you simply create your ownProgressView
:"loading"
is the name of my loading asset, you can use the asset you want (you can even find the same asset used by the Apple activity indicator).Now you can use it like in this simple example:
The result is:
This is duplicate question and was answered by user "EdYuTo" whose solution is working: https://stackoverflow.com/a/75431883/7901392