Search code examples
swiftuidismiss

what is the expected behavior of dismiss() when called by a navDestination's view?


In the code below, following the prompts, Click to select entry -> Click to populate linkedUuid, the top screen gets dismissed and goes back to the Home screen. Since dismiss() is called inside ShowAccounts view, I thought only ShowAccounts or SelectEntry gets dismissed, leaving Text("NavDest: Text-1") in tact.

The code does not behave as I expect. What Am I misunderstanding here? Thank you.


struct SO1_GAUsername: View {
    let SRC = "SO1_GAUsername"
    
    //=== Local ===
    @State private var linkedUuid: String? = "<???>"
    
    var body: some View {
        Text(SRC)
        
        HStack {
            Text("LinkEntry")
            
            Text(linkedUuid!)
                .foregroundColor(.yellow)
        }
        
        LinkEntry(linkedUuid: $linkedUuid)
    } // body
    
    struct LinkEntry: View {
        let SRC = "LinkEntry"
        
        //=== Interface ===
        @Binding var linkedUuid: String?
        
        //=== Local ===
        @Environment(\.presentationMode) @Binding private var presentationMode
        
        @State private var showSelectEntry = false

        var body: some View {
            let _ = print("\(SRC): Called")
            
            Button("Click to select entry") {
                showSelectEntry = true
            }
            .foregroundColor(.blue)
            .navigationDestination(isPresented: $showSelectEntry) {
                Text("NavDest: Text-1")
                
                SelectEntry(linkedUuid: $linkedUuid)
            } // navDest
        } // body
    } // LinkEntry
    
    struct SelectEntry: View {
        let SRC = "SelectEntry"
        
        //=== Interface ===
        @Binding var linkedUuid: String?
        
        //=== Local ===
        @Environment(\.presentationMode) @Binding private var presentationMode

        var body: some View {
            let _ = print("\(SRC): Called")
            ShowAccounts(linkedUuid: $linkedUuid)
        } // body
    } // SelectEntry
    
    struct ShowAccounts: View {
        let SRC = "ShowAccounts"
        
        //=== Interface ===
        @Binding var linkedUuid: String?
        
        //=== Local ===
        @Environment(\.presentationMode) @Binding private var presentationMode
        
        var body: some View {
            let _ = print("\(SRC): Called")
            
            Button("\(SRC): Click to populate linkedUuid") {
                let SRC = self.SRC + ".Button.click"
                
                linkedUuid = "123xyz"
                
                print("\(SRC): Dismissing")
                presentationMode.dismiss()
            }
            .foregroundColor(.blue)
        } // body
    } // ShowAccounts
} // SO1_GAUsername



Solution

  • Per Apple's doc, dismiss can be used to:

    • Dismiss a modal presentation, like a sheet or a popover.
    • Pop the current view from a NavigationStack.

    That is, dismiss() removes the entire containing view (screen), not just a contained view. Thus, the behavior described in the question is correct.