SwiftUI:在枚举上切换 .sheet,不起作用

时间:2021-02-11 20:21:13

标签: swiftui

我有两个模态/弹出框 .sheet,我想根据用户按下哪个按钮来显示。我已经设置了具有不同选择的 enum 并设置了默认选择。

预期行为:

当用户选择任何选项时,会显示正确的工作表。当用户 THEN 选择另一个选项时,它也会显示正确的工作表。

观察到的行为:

在下面的例子中,当用户第一次选择第二个选项时,第一个工作表会显示,并将继续显示,直到用户选择第一个工作表,然后它将开始切换。

调试打印显示 @State 变量正在更改,但是,工作表演示文稿未观察到此更改并按上述方式显示工作表。有什么想法吗?

import SwiftUI


//MARK: main view:
struct ContentView: View {
    
    //construct enum to decide which sheet to present:
    enum ActiveSheet {
        case sheetA, sheetB
    }
    
    //setup needed vars and set default sheet to show:
    @State var activeSheet = ActiveSheet.sheetA //sets default sheet to Sheet A
    @State var showSheet = false
    
    
    var body: some View {
        
        
        VStack{
            
            Button(action: {
                self.activeSheet = .sheetA //set choice to Sheet A on button press
                print(self.activeSheet) //debug print current activeSheet value
                self.showSheet.toggle() //trigger sheet
            }) {
                Text("Show Sheet A")
            }
            
            
            Button(action: {
                self.activeSheet = .sheetB //set choice to Sheet B on button press
                print(self.activeSheet) //debug print current activeSheet value
                self.showSheet.toggle() //trigger sheet
            }) {
                Text("Show Sheet B")
            }
        }
        
        //sheet choosing view to display based on selected enum value:
        .sheet(isPresented: $showSheet) {
            switch self.activeSheet {
            case .sheetA:
                SheetA() //present sheet A
            case .sheetB:
                SheetB() //present sheet B
            }
        }
    }
}





//MARK: ancillary sheets:
struct SheetA: View {
    var body: some View {
        Text("I am sheet A")
            .padding()
    }
}

struct SheetB: View {
    var body: some View {
        Text("I am sheet B")
            .padding()
    }
}

1 个答案:

答案 0 :(得分:5)

对您的代码进行一些非常小的改动,您可以使用 sheet(item:) 来解决这个问题:


//MARK: main view:
struct ContentView: View {
    
    //construct enum to decide which sheet to present:
    enum ActiveSheet : String, Identifiable { // <--- note that it's now Identifiable
        case sheetA, sheetB
        var id: String {
            return self.rawValue
        }
    }
    
    @State var activeSheet : ActiveSheet? = nil // <--- now an optional property
    
    var body: some View {
        
        
        VStack{
            
            Button(action: {
                self.activeSheet = .sheetA
            }) {
                Text("Show Sheet A")
            }
            
            
            Button(action: {
                self.activeSheet = .sheetB 
            }) {
                Text("Show Sheet B")
            }
        }
        //sheet choosing view to display based on selected enum value:
        .sheet(item: $activeSheet) { sheet in // <--- sheet is of type ActiveSheet and lets you present the appropriate sheet based on which is active
            switch sheet {
            case .sheetA:
                SheetA() 
            case .sheetB:
                SheetB()
            }
        }
    }
}

问题在于,如果不使用 item:,当前版本的 SwiftUI 会使用第一个状态值(即本例中的工作表 A)呈现初始工作表,并且不会在第一次演示时正确更新。使用这种 item: 方法可以解决问题。