在 swiftUI 中从多个选项显示工作表 [英] Displaying a Sheet from multiple options in 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屋!