在 swiftUI 中从多个选项显示工作表 [英] Displaying a Sheet from multiple options in swiftUI

查看:16
本文介绍了在 swiftUI 中从多个选项显示工作表的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

iOS14 引入@State 绑定错误的后续问题/p>

我根据按下的按钮显示了多个选项的模式表.但是,现在在 iOS14 中,当工作表显示时,由于 selectedSpeaker/selectedMicrophone/selectedAmp 为零,我收到了一个致命错误.我正在尝试更改为 .sheet(item:, content:) 但我看不到如何实现枚举然后传入适当的选定对象.这是我之前在做的:

enum ActiveSheet {案例 SpeakerDetails、micDetails、ampDetails、设置}

struct 收藏夹视图:查看 {@State private var selectedSpeaker:演讲者?@State private var selectedMicrophone:麦克风?@State private var selectedAmp:放大器?@State 私有变量showingSheet = false@State private var activeSheet: ActiveSheet = .settingsvar主体:一些视图{列表 {按钮(动作:{self.activeSheet = .settingsself.showingSheet = true}, label: { Text("设置")})按钮(动作:{self.activeSheet = .micDetailsself.selectedMicrophone = 麦克风[0]self.showingSheet = true}, 标签: { Text("Mic 1")})按钮(动作:{self.activeSheet = .micDetailsself.selectedMicrophone = 麦克风[1]self.showingSheet = true}, label: { Text("Mic 2")})按钮(动作:{self.activeSheet = .speakerDetailsself.showingSheet = trueself.selectedSpeaker = 扬声器[0]}, label: { Text("Speaker 1")})按钮(动作:{self.activeSheet = .speakerDetailsself.showingSheet = trueself.selectedSpeaker = 扬声器[1]}, label: { Text("Speaker 2")})//以同样的方式对 activeSheet = .ampDetails 以此类推.}.sheet(isPresented: self.$showingSheet) {如果 self.activeSheet == .speakerDetails {SpeakerDetailView(扬声器:self.selectedSpeaker!)}否则如果 self.activeSheet == .micDetails {MicDetailView(麦克风:self.selectedMicrophone!)}否则如果 self.activeSheet == .ampDetails {AmpDetailView(放大器:self.selectedAmp!)} else if self.activeSheet == .settings {SettingsView(showSheet: self.$showingSheet))}}}}}

解决方案

这是解决您的问题的另一种方法,它使用 sheet(item:content:)

struct ContentView: 查看 {@State private var selectedSpeaker:演讲者?@State private var selectedMicrophone:麦克风?@State private var selectedAmp:放大器?@State 私有 var showSettingsSheet = falsevar主体:一些视图{列表 {设置部分麦克风部分//更多部分}}var settingsSection:一些视图{按钮(动作:{self.showSettingsSheet = true}) {文本(设置")}.sheet(isPresented: self.$showSettingsSheet) {设置视图()}}@ViewBuildervarmicsSection:一些视图{按钮(动作:{self.selectedMicrophone = 麦克风[0]}) {文本(麦克风 1")}按钮(动作:{self.selectedMicrophone = 麦克风[1]}) {文本(麦克风 2")}.sheet(item: self.$selectedMicrophone) {MicDetailView(麦克风:$0)}}}

这样你也不需要enum ActiveSheet.


您始终可以使用 @Environment(\.presentationMode) 关闭工作表,无需将变量传递给工作表(如 SettingsView(showSheet: self.$showingSheet)):

struct SettingsView: View {@Environment(\.presentationMode) 私有变量presentationModevar主体:一些视图{文本(设置视图").onTapGesture {presentationMode.wrappedValue.dismiss()}}}

Follow-up question to iOS14 introducing errors with @State bindings

I was displaying a modal sheet from several options, depending on which button was pressed. However, now in iOS14 I get a fatal error caused by the selectedSpeaker/selectedMicrophone/selectedAmp being nil when the sheet displays. I am trying to change to .sheet(item:, content:) but I can't see how to implement the enum and then pass in the appropriate selected object. This is what I was doing previously:

enum ActiveSheet {
    case speakerDetails, micDetails, ampDetails, settings
}

struct FavoritesView: View {
    @State private var selectedSpeaker: Speaker?
    @State private var selectedMicrophone: Microphone?
    @State private var selectedAmp: Amplifier?

    @State private var showingSheet = false
    @State private var activeSheet: ActiveSheet = .settings  

    var body: some View {
    
    List {
        Button(action: {
            self.activeSheet = .settings
            self.showingSheet = true
            }, label: { Text("Settings")})

        Button(action: {
            self.activeSheet = .micDetails
            self.selectedMicrophone = microphones[0]
            self.showingSheet = true
            }, label: { Text("Mic 1")})

        Button(action: {
            self.activeSheet = .micDetails
            self.selectedMicrophone = microphones[1]
            self.showingSheet = true
            }, label: { Text("Mic 2")})

        Button(action: {
            self.activeSheet = .speakerDetails
            self.showingSheet = true
            self.selectedSpeaker = speakers[0]
            }, label: { Text("Speaker 1")})

        Button(action: {
            self.activeSheet = .speakerDetails
            self.showingSheet = true
            self.selectedSpeaker = speakers[1]
            }, label: { Text("Speaker 2")})

    //and so on for activeSheet = .ampDetails in the same way.
        
    }
      .sheet(isPresented: self.$showingSheet) {
                if self.activeSheet == .speakerDetails {
                    SpeakerDetailView(speaker: self.selectedSpeaker!)
                }
                else if self.activeSheet == .micDetails {
                MicDetailView(microphone: self.selectedMicrophone!)
                }
                else if self.activeSheet == .ampDetails {
                AmpDetailView(amp: self.selectedAmp!)
                } else if self.activeSheet == .settings {
                    SettingsView(showSheet: self.$showingSheet))
                }
            }
        }
    }
}

解决方案

Here is another approach for your problem which uses sheet(item:content:)

struct ContentView: View {
    @State private var selectedSpeaker: Speaker?
    @State private var selectedMicrophone: Microphone?
    @State private var selectedAmp: Amplifier?
    @State private var showSettingsSheet = false

    var body: some View {
        List {
            settingsSection
            microphonesSection
            // more sections
        }
    }
    
    var settingsSection: some View {
        Button(action: {
            self.showSettingsSheet = true
        }) {
            Text("Settings")
        }
        .sheet(isPresented: self.$showSettingsSheet) {
            SettingsView()
        }
    }
    
    @ViewBuilder
    var microphonesSection: some View {
        Button(action: {
            self.selectedMicrophone = microphones[0]
        }) {
            Text("Mic 1")
        }
        Button(action: {
            self.selectedMicrophone = microphones[1]
        }) {
            Text("Mic 2")
        }
        .sheet(item: self.$selectedMicrophone) {
            MicDetailView(microphone: $0)
        }
    }
}

This way you also don't need enum ActiveSheet.


You can always use @Environment(\.presentationMode) to dismiss a sheet, no need to pass the variable to the sheet (as in SettingsView(showSheet: self.$showingSheet)):

struct SettingsView: View {
    @Environment(\.presentationMode) private var presentationMode

    var body: some View {
        Text("SettingsView")
            .onTapGesture {
                presentationMode.wrappedValue.dismiss()
            }
    }
}

这篇关于在 swiftUI 中从多个选项显示工作表的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆