Reputation: 289
I have a SwiftUI view with a button "Show sheet", when that button is pressed I would like to present the first view on the sheet. That view has a button to dismiss itself. If the Show sheet button is pressed again, now I would like to present the second view on the sheet, and it also has dismiss button. Here is the code:
struct FirstSheetView: View {
@Binding var isPresented: Bool
var body: some View {
Button("Dismiss") {
self.isPresented = false
}
}
}
struct SecondSheetView: View {
@Binding var isPresented: Bool
var body: some View {
Button("Dismiss") {
self.isPresented = false
}
}
}
enum ActiveSheet {
case first, second
}
struct ContentView: View {
@State private var isShowingPhotoSheet = false
@State private var activeSheet: ActiveSheet = .first
var body: some View {
VStack {
Button(action: {
self.isShowingPhotoSheet.toggle()
}) {
Text("Show sheet")
}
}
.sheet(
isPresented: $isShowingPhotoSheet,
onDismiss: loadSecondView,
content: {
if self.activeSheet == .first {
FirstSheetView(isPresented: self.$isShowingPhotoSheet)
} else {
SecondSheetView(isPresented: self.$isShowingPhotoSheet)
}
}
)
}
private func loadSecondView() {
activeSheet = .second
self.isShowingPhotoSheet.toggle()
}
}
The sheets are shown just fine, I am able to dismiss the first sheet, but not the second one (only with swiping it down), but it doesn't seem to do anything by pressing the "Dismiss" button. What could be the problem?
Upvotes: 2
Views: 676
Reputation: 257749
The problem is that onDismiss
is too early to set up second sheet, first one is still on screen and bound to state.
Here is a solution. Tested with Xcode 11.4 / iOS 13.4
private func loadSecondView() {
if activeSheet == .second {
activeSheet = .first
} else {
activeSheet = .second
// give time to close first sheet
DispatchQueue.main.asyncAfter(deadline: .now() + 0.5) {
self.isShowingPhotoSheet = true
}
}
}
Upvotes: 2