I'm having my View
's reload when my TabView
tab changes. I'm trying to show a ProgressView
while fetching data from an API on initial data loading, but it's being reloaded every tab change, even after navigating to another view. If I remove my ProgressView
it works, it just doesn't look great when loading data.
I assumed this would have been a simple task, but I haven't found a great solution. I found StatefulTabView but it seems broken on iOS 15. I'm not sure if I'm just doing something incorrectly with my view model. Any help would be appreciated.
view model
class RickAndMortyViewModel: ObservableObject {
private var cancellables = Set<AnyCancellable>()
@Published var dataone = RickandMorty(results: [])
@Published var datatwo = RickandMorty(results: [])
@Published var loadingone: Bool = false
@Published var loadingtwo: Bool = false
func getpageone() {
self.loadingone = true
URLSession.shared.dataTaskPublisher(for:URLRequest(url: URL(string: "https://rickandmortyapi.com/api/character/?page=1")!))
.map{ $0.data }
.decode(type: RickandMorty.self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { results in
switch results {
case .finished:
self.loadingone = false
case .failure(let error):
print(error)
}
},receiveValue: { data in
self.dataone = data
})
.store(in: &cancellables)
}
func getpagetwo() {
self.loadingtwo = true
URLSession.shared.dataTaskPublisher(for:URLRequest(url: URL(string: "https://rickandmortyapi.com/api/character/?page=2")!))
.map{ $0.data }
.decode(type: RickandMorty.self, decoder: JSONDecoder())
.receive(on: DispatchQueue.main)
.sink(receiveCompletion: { results in
switch results {
case .finished:
self.loadingtwo = false
case .failure(let error):
print(error)
}
},receiveValue: { data in
self.datatwo = data
})
.store(in: &cancellables)
}
}
view
struct ContentView: View {
@StateObject var viewmodel = RickAndMortyViewModel()
var body: some View {
TabView {
NavigationView {
if viewmodel.loadingone {
ProgressView("Loading Page 1")
.navigationTitle("Page 1")
} else {
List {
ForEach(viewmodel.dataone.results, id: \.id) { character in
NavigationLink(destination: EmptyView()) {
Text(character.name)
}
}
}
.navigationTitle("Page 1")
}
}
.onAppear {
viewmodel.getpageone()
}
.tabItem {
Label("Page 1", systemImage: "person")
}
.tag(1)
NavigationView {
if viewmodel.loadingtwo {
ProgressView("Loading Page 2")
.navigationTitle("Page 2")
} else {
List {
ForEach(viewmodel.datatwo.results, id: \.id) { character in
NavigationLink(destination: EmptyView()) {
Text(character.name)
}
}
}
.navigationTitle("Page 2")
}
}
.onAppear {
viewmodel.getpagetwo()
}
.tabItem {
Label("Page 2", systemImage: "person")
}
.tag(2)
}
}
}