2

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

1 Answer 1

1

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() } } } 
Sign up to request clarification or add additional context in comments.

Comments

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.