swiftswiftui

Unclear behavior of the view with navigation and presentationBackground


I have a problem with the presentationBackground modifier. When using it in a real application, I noticed strange behavior upon returning to the root view, where it seems like two views overlap each other. In a sample app created for the purpose of this question, it looks like this:

enter image description here

Step to reproduce:

  1. Open sheet
  2. Add new item
  3. Open & dismiss sheet
  4. Tap on back or 'New item' button

Here is example (working) code

import SwiftUI

struct ContentView: View {
    
    @State var newItem: String?
    @State var sheetPresented = false
    
    var body: some View {
        NavigationStack {
            Button {
                sheetPresented = true
            } label: {
                Text("Open sheet")
            }
            .sheet(isPresented: $sheetPresented) {
                NavigationStack {
                    Button {
                        newItem = "New item"
                    } label: {
                        Text("Add new item")
                    }
                    .navigationDestination(item: $newItem) { item in
                        NavigationStack {
                            NewItemDetails(item: item)
                        }
                    }
                }
            }
        }
    }
}

struct NewItemDetails: View {
    @Environment(\.dismiss) var dismiss
    @State var openSheet = false
    let item: String
    
    init(item: String) {
        self.item = item
    }
    
    var body: some View {
        VStack(spacing: 20) {
            Button {
                dismiss()
            } label: {
                Text(item)
            }
            Button {
                openSheet = true
            } label: {
                Text("Open sheet")
            }
        }
        .sheet(isPresented: $openSheet) {
            Button {
                openSheet = false
            } label: {
                Text("After dismiss tap to 'New item' or Back")
            }
            .presentationBackground {
                Color.red
            }
        }
    }
}

#Preview {
    ContentView()
}

Expected result: enter image description here

Does anyone know why this is happening? Is it a bug, or is it more likely due to an oversight or incorrect view structure on my part?


Solution

  • This seems like a SwiftUI bug to me. I'd suggest submitting feedback to Apple.

    For now, you can work around this by adding a presentationBackground to the first sheet as well. If you use .background, it will look the same as if you did not add a presentationBackground modifier.

    .sheet(isPresented: $sheetPresented) {
        NavigationStack {
            Button {
                newItem = "New item"
            } label: {
                Text("Add new item")
            }
            .navigationDestination(item: $newItem) { item in
                // don't nest another NavigationStack here!
                NewItemDetails(item: item)
            }
        }
        .presentationBackground(.background) // <----
    }