SwiftUI incorrectly instantiating navigation destination with new identity when navigation stack is removed

There is an issue with SwiftUI where it is incorrectly instantiating the navigation destination view with a new identity for a navigation stack that is being removed.

Here is a minimal reproducible example:

struct ContentView: View {
    @State private var signedIn = false
    
    var body: some View {
        if signedIn {
            navigationStack(isSignedIn: true)
        } else {
            navigationStack(isSignedIn: false)
        }
    }
    
    private func navigationStack(isSignedIn: Bool) -> some View {
        NavigationStack(path: .constant(NavigationPath([1]))) {
            EmptyView()
                .navigationDestination(for: Int.self) { _ in
                    VStack {
                        Text(isSignedIn ? "Signed In" : "Signed Out")
                            .foregroundStyle(Color.red)
                        Button(isSignedIn ? "Sign Out" : "Sign In") {
                            signedIn = !isSignedIn
                        }
                    }
                    .onFirstAppear {
                        print(isSignedIn ? "signed in" : "signed out")
                    }
                }
        }
    }
}


struct OnFirstAppearView: ViewModifier {
    @State private var hasAppeared = false
    
    var onAppear: () -> Void
    
    func body(content: Content) -> some View {
        content
            .onAppear {
                if hasAppeared { return }
                hasAppeared = true
                onAppear()
            }
    }
}

extension View {
    func onFirstAppear(_ onAppear: @escaping () -> Void) -> some View {
        ModifiedContent(content: self, modifier: OnFirstAppearView(onAppear: onAppear))
    }
}

When you launch the app it will print "signed out", but when you tap to Sign In it will print "signed out" and "signed in". This shows that onAppear is incorrectly being called for a view that is disappearing and worse yet, it is with a new identity.

The onFirstAppear modifier was created to help with detecting the identity change of the view.

Tested on Xcode 16.4, on simulator using iOS 18.5 and also on physical device using iOS 18.5.

Link to Feedback sent on Feedback Assistant: https://feedbackassistant.apple.com/feedback/18336684

SwiftUI incorrectly instantiating navigation destination with new identity when navigation stack is removed
 
 
Q