I am facing an issue while pushing 1 view to another view. Let me explain the hierarchy.
ContentView -> 2 tabs, TabAView and TabBView Inside TabBView. There is 1 view used ConnectView: Where is a Button to connect. After tapping on the button of Connect, the user move to another View which is called as UserAppView.
Here is the code to understand better my problem.
ContentView.swift
struct ContentView: View {
enum AppPage: Int {
case TabA=0, TabB=1
}
@StateObject var settings = Settings()
@ObservedObject var userViewModel: UserViewModel
@ObservedObject var userAppViewModel: UserAppViewModel
var body: some View {
NavigationView {
TabView(selection: $settings.tabItem) {
TabAView(userViewModel: userViewModel, userAppViewModel: userAppViewModel)
.tabItem {
Text("TabA")
}
.tag(AppPage.TabA)
TabBView(userViewModel: userViewModel, userAppViewModel: userAppViewModel)
.tabItem {
Text("Apps")
}
.tag(AppPage.TabB)
}
.accentColor(.white)
.edgesIgnoringSafeArea(.top)
.onAppear(perform: {
settings.tabItem = .TabA
})
.navigationBarTitleDisplayMode(.inline)
}
.environmentObject(settings)
}
}
This is TabAView:
struct TabAView: View {
@ObservedObject var userViewModel: UserViewModel
@ObservedObject var userAppViewModel: UserAppViewModel
@EnvironmentObject var settings: Settings
init(userViewModel: UserViewModel, userAppViewModel: UserAppViewModel) {
self.userViewModel = userViewModel
self.userAppViewModel = userAppViewModel
}
var body: some View {
Vstack {
/// code
}
.onAppear(perform: {
/// code
})
.environmentObject(settings)
}
}
This is another TabBView:
struct TabBView: View {
@ObservedObject var userViewModel: UserViewModel
@ObservedObject var userAppViewModel: UserAppViewModel
init(userViewModel: UserViewModel, userAppViewModel: UserAppViewModel) {
self.userViewModel = userViewModel
self.userAppViewModel = userAppViewModel
}
var body: some View {
VStack (spacing: 10) {
NavigationLink(destination: ConnectView(viewModel: ConnectViewModel(id: id!), userViewModel: userViewModel, userAppViewModel: userAppViewModel)) {
UserCardWidget()
}
}
}
}
There is 1 connectView used on the TabBView through which the user will connect. ConnectViewModel is used here to call connect API.
class ConnectViewModel: ObservableObject {
var id: String?
init(id: String) {
self.id = id
}
func connect(completion: @escaping () -> Void) {
APIService.shared.connectApp(id: self.id!) { connected in
DispatchQueue.main.async {
self.isConnected = connected ?? false
completion()
}
}
}
}
This is connect view
struct ConnectView: View {
@ObservedObject var connectViewModel: ConnectViewModel
@ObservedObject var userViewModel: UserViewModel
@ObservedObject var userAppViewModel: UserAppViewModel
@State var buttonTitle = "CONNECT WITH THIS"
@State var isShowingDetailView = false
var body: some View {
VStack {
Spacer()
if let id = connectViewModel.id {
NavigationLink(destination: UserAppView(id: id, userAppViewModel: userAppViewModel, userViewModel: userViewModel), isActive: $isShowingDetailView) {
Button(buttonTitle, action: {
connectViewModel.connect {
buttonTitle = "CONNECTED"
isShowingDetailView = true
}
})
}
}
}
}
}
This is the UserAppViewModel where API is hit to fetch some user-related details:
class UserAppViewModel: ObservableObject {
var id = ""
func getdetails() {
APIService.shared.getDetails() { userDetails in
DispatchQueue.main.async {
/// code
}
}
}
}
This is UserAppView class
struct UserAppView: View {
@ObservedObject var userViewModel: UserViewModel
@ObservedObject var userAppViewModel: UserAppViewModel
init(id: String, userAppViewModel: UserAppViewModel, userViewModel: UserViewModel) {
self.id = id
self.userAppViewModel = userAppViewModel
self.userViewModel = userViewModel
}
var body: some View {
VStack {
Text(userAppViewModel.status)
}.onAppear(perform: {
**userAppViewModel.getDetails**(id: id)
})
}
}
Whenever this statement userAppViewModel.getDetails executes, the user comes to UserAppView but when the response of getDetails is received, it automatically goes to ConnectView.
I have removed most of the code from a confidential point of view but this code will explain the reason and error. Please look into the code and help me.