简体   繁体   English

为什么 .sheet(item) 修饰符在 SwiftUI 的工具栏中不起作用?

[英]Why does .sheet(item) Modifier not work inside Toolbar in SwiftUI?

Context语境

I have a Menu (including multiple Buttons ) inside a SwiftUI Toolbar and a .sheet() Modifier inside the Toolbar , too.我在SwiftUI Toolbar内有一个Menu (包括多个Buttons ),在Toolbar内也有一个.sheet() Modifier

The problem is, that pressing the Button with the show.toggle() action does not present the Sheet as expected.问题是,使用show.toggle()操作按下Button不会按预期显示工作Sheet

Important: I noticed the weird behaviour, that when I give showOption an initial value like var showOption: Option? =.option1重要提示:我注意到奇怪的行为,当我给showOption一个初始值时,比如var showOption: Option? =.option1 var showOption: Option? =.option1 , this works perfectly fine (except the initial Sheet popup of course). var showOption: Option? =.option1 ,这工作得很好(当然初始工作Sheet弹出窗口除外)。 However, once I initiate the showOption property with nil , it breaks.但是,一旦我使用nil启动showOption属性,它就会中断。


Code代码

struct MainView: View {
    var showOption: Option?
    // var showOption: Option? = .option -> this would work perfectly fine.

    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?这是由Toolbar栏内的.sheet()引起的,还是我遗漏了其他任何内容?
  • How can I solve this (ideally without moving the .sheet() outside of the Toolbar )?我该如何解决这个问题(最好不要将.sheet()移到Toolbar之外)?

if you move it outside of Menu (still in Toolbar) it works fine:如果你将它移出Menu (仍在工具栏中)它工作正常:

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")
                        }
                    }
                }
        }
    }
}

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.在 SwiftUI 中,每当我们应用修饰符来查看它时,它实际上会创建一个应用了该更改的新视图,而不是修改该位置的现有视图。 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 Swift 的type(of:)方法打印特定视图/值的确切类型,如果我们在Menu下添加.sheet修饰符, print(of:)显示以下内容 output

ModifiedContent<Text, ToolbarModifier<(), TupleToolbarContent<ToolbarItem<(), ModifiedContent<Menu<Text, Button>, SheetPresentationModifier>>>>> 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按以下方式嵌套元素:Text -> ToolbarModifier -> TupleToolbarContent -> ToolbarItem -> ModifiedContent -> Menu -> Text -> Button -> SheetPresentationModifier

if we add the .sheet modifier under the button print(of:) shows the following output如果我们在按钮print(of:)下添加.sheet修饰符,则显示以下 output

ModifiedContent<Text, ToolbarModifier<(), TupleToolbarContent<ToolbarItem<(), Menu<Text, ModifiedContent<Button, SheetPresentationModifier>>>>> 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按以下方式嵌套元素: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.因此,正如我们之前讨论的那样,修饰符的顺序会影响 SwiftUI 的功能。如果我们将.sheet添加到Menu元素,那么它将具有特定于 ModifiedContent 的附加功能或外观并显示工作表。 While for the case of button ModifiedContent does not work.而对于按钮ModifiedContent 的情况不起作用。

The answer is still the same and it still works, if you move .sheet out of the Menu :如果您将.sheet移出Menu ,答案仍然相同并且它仍然有效:

enum Option: Int, Identifiable {
    case option1 = 1
    case option2 = 2
    case option3 = 3
    
    var id: Int { self.rawValue }
}

struct ContentView: View {
    @State private var showOption: Option?
    
    var body: some View {
        NavigationStack {
            Text("Hello World")
                .toolbar {
                    ToolbarItem {
                        Menu("Menu") {
                            Button("1") { showOption = .option1 }
                            Button("2") { showOption = .option2 }
                            Button("3") { showOption = .option3 }
                        }
                        .sheet(item: $showOption) { option in
                            Text("Hello World \(option.rawValue)")
                        }
                    }
                }
        }
    }
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM