Search code examples
swiftui-navigationlinkswiftui

SwiftUI doubly nested NavigationLink views not responding to changing ObservedObject


I've created three views. I'm passing ObservedObject state to each view in sequence. When I change the state in the last view (AnotherView2), my application does not show the Text view with 'YES IT IS FINISHED!'. However, if I uncomment this line in AnotherView

self.userDefaultsManager.setupComplete = true

it works as I expected by showing the text.


struct ContentView: View {

    @ObservedObject var userDefaultsManager = UserDefaultsManager()
    @State var showAnotherView: Bool = false

    var body: some View {
        NavigationView {
            VStack {
                if !userDefaultsManager.setupComplete {
                    Button(action: {
                        self.showAnotherView.toggle()
                    }) {
                        Text("Show Another View")
                    }
                    NavigationLink(destination: AnotherView(userDefaultsManager: userDefaultsManager), isActive: $showAnotherView, label: {
                        EmptyView()
                    })
                } else {
                    Text("YES IT IS FINISHED!")
                }

            }
        }
    }
}


struct AnotherView: View {

    @ObservedObject var userDefaultsManager: UserDefaultsManager
    @State var showAnotherView2: Bool = false

    var body: some View {
        VStack {
            Button(action: {
                //self.userDefaultsManager.setupComplete = true
                self.showAnotherView2 = true
            }, label: {
                Text("Press")
            })
            NavigationLink(destination: AnotherView2(userDefaultsManager: userDefaultsManager), isActive: $showAnotherView2, label: {
                EmptyView()
            })
        }
    }
}


struct AnotherView2: View {

    @ObservedObject var userDefaultsManager: UserDefaultsManager

    var body: some View {
        Button(action: {
            self.userDefaultsManager.setupComplete = true
        }, label: {
            Text("Just Do It")
        })
    }
}


class UserDefaultsManager: ObservableObject {

    @Published var setupComplete: Bool = UserDefaults.standard.bool(forKey: "setupComplete") {
        didSet { UserDefaults.standard.set(self.setupComplete, forKey: "setupComplete") }
    }
}

Can someone help me understand what is wrong with my code or the API that it won't work on double nested calls to show views in this manner?

EDIT: Using XCode 11.3 & iOS 13.3.1


Solution

  • I suppose here is a layout that gives required behaviour

    var body: some View {
        Group {
            if !userDefaultsManager.setupComplete {
                NavigationView {
                    VStack {
                        Button(action: {
                            self.showAnotherView.toggle()
                        }) {
                            Text("Show Another View")
                        }
                        NavigationLink(destination: AnotherView(userDefaultsManager: userDefaultsManager), isActive: $showAnotherView, label: {
                            EmptyView()
                        })
                    }
                }
            } else {
                Text("YES IT IS FINISHED!")
            }
        }
    }