Home > Back-end >  Why does .sheet(item) Modifier not work inside Toolbar in SwiftUI?
Why does .sheet(item) Modifier not work inside Toolbar in SwiftUI?

Time:01-25

Context

I have a Menu (including multiple Buttons) inside a SwiftUI Toolbar and a .sheet() Modifier inside the Toolbar, too.

The problem is, that pressing the Button with the show.toggle() action does not present the Sheet as expected.

Please Note: My actual app architecture is more complex than this MRE, so moving the .sheet() outside of the Toolbar is pretty difficult.


Code

struct MainView: View {
    var showOption: Option?

    var body: some View {
        NavigationStack {
            Text("Hello World")
                .toolbar {
                    ToolbarItem {
                        Menu { 
                            ... Button(action: { option = .option1 } { ... } ... 
                        }
                        .sheet(item: $showOption) { option in
                            switch option {
                            case .option1: Text("Hello World 1")
                            ...
                            }
                        }
                    }
                }
        }
    }
}

Questions

  • Is this caused by the .sheet() being inside the Toolbar or is there anything else I missed?
  • How can I solve this (ideally without moving the .sheet() outside of the Toolbar)?

CodePudding user response:

if you move it outside of Menu (still in Toolbar) it works fine:

struct ContentView: View {
    
    @State private var show: Bool = false
    
    var body: some View {
        NavigationStack {
            Text("Hello World")
                .toolbar {
                    ToolbarItem {
                        Menu("Test") {
                            Button("Show") {
                                show.toggle()
                            }
                        }
                        .sheet(isPresented: $show) {
                            Text("Hello World 2")
                        }
                    }
                }
        }
    }
}

CodePudding user response:

In SwiftUI whenever we apply a modifier to view it actually create a new view with that change applied instead of modifying the existing view in the place. This behavior makes sense: our views only hold the exact properties we give them. Have a look at the sample code below.

struct ContentView: View {
    
    @State private var show: Bool = false
    
    var body: some View {
        NavigationStack {
            Text("Hello World")
                .toolbar {
                    ToolbarItem {
                        Menu("Test") {
                            Button("Show") {
                                print(type(of: self.body))
                                show.toggle()
                            }
                        }
                        .sheet(isPresented: $show) {
                            Text("Hello World 2")
                        }
                    }
                }
        }
    }
}

Swift’s type(of:) method prints the exact type of a particular view/value, if we add the .sheet modifier under the Menu, print(of:) shows the following output

ModifiedContent<Text, ToolbarModifier<(), TupleToolbarContent<ToolbarItem<(), ModifiedContent<Menu<Text, Button>, SheetPresentationModifier>>>>>

Nests the elements in the following way: Text -> ToolbarModifier -> TupleToolbarContent -> ToolbarItem -> ModifiedContent -> Menu -> Text -> Button -> SheetPresentationModifier

if we add the .sheet modifier under the button print(of:) shows the following output

ModifiedContent<Text, ToolbarModifier<(), TupleToolbarContent<ToolbarItem<(), Menu<Text, ModifiedContent<Button, SheetPresentationModifier>>>>>

Nest the elements in the following way: Text -> ToolbarModifier -> TupleToolbarContent -> ToolbarItem -> Menu -> Text -> ModifiedContent -> Button -> SheetPresentationModifier

So, as we discussed earlier that the order of modifier effect on the functionality of SwiftUI. If we add .sheet to the Menu element then it would have additional functionality or appearance that is specific to the ModifiedContent and shows the sheet. While for the case of button ModifiedContent does not work.

  • Related