I have an app with 4 tabs. Each tab has its own view model. The user flow is:
Open app
Click on tab 4
Select the TextField
My expectation was that on tab 4 selection the onAppear's would execute for that tab. Then on textfield selection nothing would happen.. instead all tab views are rendering.
Why and how do I make those other tabs not render on selection?
Her is the user flow results and code:
// ON LOAD
1 simple view appear
1 get people
tab 1 appear
1 get people
// SELECT TAB 4
4 simple view appear
4 get people
tab 4 appear
4 get people
// FOCUS TAB 4 TEXTFIELD -> ALL TABS RENDER
! Why are these tabs rendering?
2 simple view appear
2 get people
tab 2 appear
2 get people
3 simple view appear
3 get people
tab 3 appear
3 get people
tab 1 appear
1 get people
1 simple view appear
1 get people
Content View
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@ObservedObject var viewModel1: ViewModel = ViewModel()
@ObservedObject var viewModel2: ViewModel = ViewModel()
@ObservedObject var viewModel3: ViewModel = ViewModel()
@ObservedObject var viewModel4: ViewModel = ViewModel()
var body: some View {
TabView {
SimpleView(viewModel: self.viewModel1, people: viewModel1.people, num: 1)
.tabItem {
Text("1")
}.onAppear{
print("tab 1 appear")
viewModel1.getPeople(num: 1)
}
SimpleView(viewModel: self.viewModel2, people: viewModel2.people, num: 2)
.tabItem {
Text("2")
}.onAppear{
print("tab 2 appear")
viewModel2.getPeople(num: 2)
}
SimpleView(viewModel: self.viewModel3, people: viewModel3.people, num: 3)
.tabItem {
Text("3")
}.onAppear{
print("tab 3 appear")
viewModel3.getPeople(num: 3)
}
SimpleView(viewModel: self.viewModel4, people: viewModel4.people, num: 4)
.tabItem {
Text("4")
}.onAppear{
print("tab 4 appear")
viewModel4.getPeople(num: 4)
}
}
}
}
Model
import Foundation
struct Person: Identifiable, Equatable {
let id = UUID()
let name: String
}
class ViewModel: ObservableObject {
@Published var people: [Person] = []
func getPeople(num: Int) {
print("\(num) get people")
DispatchQueue.main.async {
let person = Person(name: "Hank \(num)")
self.people.append(person)
}
}
}
View Model
import SwiftUI
struct SimpleView: View {
@State var text: String = ""
@State var viewModel: ViewModel
var people: [Person]
var num: Int
var body: some View {
VStack {
TextField("Enter text", text: self.$text)
ForEach(viewModel.people) { person in
Text(person.name)
}
}.onAppear {
print("\(num) simple view appear")
viewModel.getPeople(num: num)
}
}
}