I'm trying to use the refreshable modifier on a Scrollview in an app that targets iOS 16. But the asynchronus task gets cancelled during the pull to refresh gesture. It was tested on a physical device.
Here is some code that demonstrates the problem and an image with the error printed:
ExploreViewModel.swift
class ExploreViewModel: ObservableObject {
@Published var randomQuotes: [Quote] = []
init() {
Task {
await loadQuotes()
}
}
@MainActor
func loadQuotes() async {
let quotesURL = URL(string: "https://type.fit/api/quotes")!
do {
let (data, urlResponse) = try await URLSession.shared.data(from: quotesURL)
guard let response = urlResponse as? HTTPURLResponse else { print("no response"); return}
if response.statusCode == 200 {
let quotes = try JSONDecoder().decode([Quote].self, from: data)
randomQuotes.append(contentsOf: quotes)
}
} catch {
debugPrint(error)
debugPrint(error.localizedDescription)
}
}
func clearQuotes() {
randomQuotes.removeAll()
}
}
Content.swift
import SwiftUI
struct ContentView: View {
@StateObject private var exploreVM = ExploreViewModel()
var body: some View {
NavigationStack {
ExploreView()
.environmentObject(exploreVM)
.refreshable {
exploreVM.clearQuotes()
await exploreVM.loadQuotes()
}
}
}
}
ExploreView.swift
import SwiftUI
struct ExploreView: View {
@EnvironmentObject var exploreVM: ExploreViewModel
var body: some View {
ScrollView {
VStack {
LazyVGrid(columns: [GridItem(.adaptive(minimum: 140.0), spacing: 24.0)], spacing: 24.0) {
ForEach(exploreVM.randomQuotes) { quote in
VStack(alignment: .leading) {
Text("\(quote.text ?? "No Text")")
.font(.headline)
Text("\(quote.author ?? "No Author")")
.font(.caption)
}
.frame(minWidth: 0, maxWidth: .infinity)
.frame(height: 144.0)
.border(Color.red, width: 2.0)
}
}
}
.padding()
.navigationTitle("Explore")
}
}
}
Printed Error