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

zd287kbt  于 2023-01-29  发布在  Swift
关注(0)|答案(3)|浏览(169)
    • bounty将在5天后过期**。回答此问题可获得+50的声誉奖励。christophriepe正在寻找此问题的更详细的答案
    • 背景**

我在SwiftUIToolbar中有一个Menu(包括多个Buttons),在Toolbar中也有一个.sheet()Modifier
问题是,使用show.toggle()操作按下Button不会按预期显示Sheet

    • 重要提示:**我注意到了一个奇怪的行为,当我给showOption一个像var showOption: Option? = .option1这样的初始值时,它工作得非常好 (当然除了初始的Sheet弹出窗口)。 但是,一旦我用nil初始化showOption属性,它就崩溃了。
    • 代码**
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")
                            ...
                            }
                        }
                    }
                }
        }
    }
}
    • 问题**
  • 这是由于.sheet()位于Toolbar内部造成的,还是我遗漏了其他内容?
  • 如何解决这个问题(理想情况下,不需要将.sheet()移出Toolbar)?
ar7v8xwq

ar7v8xwq1#

如果您将其移出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")
                        }
                    }
                }
        }
    }
}
6tr1vspr

6tr1vspr2#

在SwiftUI中,每当我们应用修改器来查看它时,它实际上创建了一个应用了该更改的新视图,而不是修改该位置的现有视图。我们的视图只保留我们给予它们的确切属性。2请看下面的示例代码。

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的type(of:)方法打印特定视图/值的确切类型,如果我们在Menu下添加.sheet修饰符,print(of:)将显示以下输出
已修改内容〈文本,工具栏修饰符〈(),元组工具栏内容〈工具栏项〈(),已修改内容〈菜单〈文本,按钮〉,图纸演示修饰符〉〉〉〉
按以下方式嵌套元素:文本-〉工具栏修饰符-〉元组工具栏内容-〉工具栏项目-〉ModifiedContent -> Menu -> Text -> Button -> SheetPresentationModifier
如果我们在按钮下添加.sheet修饰符print(of:)将显示以下输出
已修改内容〈文本,工具栏修饰符〈(),元组工具栏内容〈工具栏项〈(),菜单〈文本,已修改内容〈按钮,图纸演示修饰符〉〉〉〉
按以下方式嵌套元素:文本-〉工具栏修改器-〉元组工具栏内容-〉工具栏项目-〉菜单-〉文本-〉修改的内容-〉按钮-〉图纸演示修改器
因此,正如我们之前讨论的,修饰符的顺序会影响SwiftUI的功能。如果我们将.sheet添加到Menu元素,则它将具有特定于ModifiedContent的附加功能或外观,并显示表单。而对于buttonModifiedContent的情况,则不起作用。

3zwtqj6y

3zwtqj6y3#

如果将.sheetMenu中移出,答案仍然相同,并且仍然有效:

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

相关问题