'TabView freezes when navigating back to initial tab

I have my ContentView with 2 tabs.

struct ContentView: View {
    var formViewModel = ViewModel()

    var body: some View {
        TabView {
            HomeTab()
                .environmentObject(formViewModel)
                .tabItem {
                    Label("Home", systemImage: "house")
                }


            SettingsTab()
                .tabItem {
                    Label("Settings", systemImage: "gear")
                }
        }
    }
}

HomeTab is a simple view with a button that moves to the detail page. Same as the SettingsTab.

struct HomeTab: View {
    @EnvironmentObject var formViewModel: ViewModel

    var body: some View {
        NavigationView {
            NavigationLink(destination: DetailView().environmentObject(formViewModel)) {
                Text("Move to Detail Page")
            }
        }
    }
}

SettingsTab:

struct SettingsTab: View {
    var body: some View {
        NavigationView {
            Text("Settings")
        }
    }
}

Inside DetailView is a single Textfield binded to a Published String? in the ViewModel. setInitialValues gives it a value and deactivate sets the value to nil

struct DetailView: View {
    @EnvironmentObject var vm: ViewModel

    var body: some View {
        TextField("Enter stuff", text: Binding<String>(
            get: { vm.password ?? "" },
            set: { vm.password = $0 }
        ))
            .padding()
            .onAppear {
                vm.activate()
                vm.setInitialValues("Solar Power")
            }
            .onDisappear {
                vm.deactivate()
            }
    }

}

Naturally, when you move from HomeTab to the DetailView and switch tabs to the SettingsTab, you should be able to switch back to the DetailView in the previous tab. But in this case, the screen freezes. This only occurs on iPhone X + devices.

When you set the textfield's text property to a .constant("details"), it works alright (You are able to switch between tabs without it freezing).

I should add that, onAppear of DetailView is being called when you switch back. The data is also present as I can log it. But the screen just freezes.

Edit:

I've realized its freezing from the textfield's binding. Logs from the getter and setter keep showing like this (while the screen is stuck):

Log from switching tabs



Solution 1:[1]

Your view model in ContentView should be declared as a @StateObject. Otherwise it’s going to get re-initialized every time SwiftUI thinks about whether or not to redraw the screen. That process causes new instances of all the views to be loaded into memory, and right now each time it loads a ContentView it will create a new view model.

struct ContentView: View {
  @StateObject var formViewModel = ViewModel()
  // etc.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 ScottM