I experience some weird behavior since updating to Xcode 12 / iOS 14. To verify this behavior, I isolated it in a test app.
In my original app, I have multiple Sheets to control. This is why I have en enum to differentiate between the currently active sheet and I store this in a @State private var activeSheet. In the @ViewBuilder function sheetContent() I return the View for the selected Sheet.
For this test app, I only implemented one single sheet for simplicity reasons.
Here's the ContentView's code:
struct ContentView: View {
@State private var showingSheet = false
@State private var activeSheet = ContentViewSheets.State.none
var body: some View {
Button(action: {
activeSheet = .aSheet
showingSheet = true // <-- ISSUE: activeSheet is still set to .none here!
}) {
Text("Open Sheet")
}
.sheet(isPresented: $showingSheet, content: sheetContent)
}
@ViewBuilder
private func sheetContent() -> some View {
switch activeSheet {
case .aSheet:
Text("I'm the right sheet!")
case .none:
Text("Oops! I'm not supposed to show up!")
}
}
}
This is the code for the enum:
class ContentViewSheets {
enum State {
case aSheet
case none
}
}
As commented in the ContentView code above, the value of the activeSheet property is never changed to .aSheet, but remains .none - so that the wrong sheet will be presented.
Is this a bug or didn't I properly understand Apple's @State? They just write in the documentation that it shall not be used in initializer, but only within the body, which I definitely do.
Instead of using two states, use one and explicitly designed sheet modifier for such scenarios.
Tested with Xcode 12 / iOS 14
class ContentViewSheets {
enum State: Identifiable {
case aSheet
case none
var id: State { self }
}
}
struct ContentView: View {
@State private var activeSheet: ContentViewSheets.State?
var body: some View {
Button(action: {
activeSheet = .aSheet
}) {
Text("Open Sheet")
}
.sheet(item: $activeSheet) {
sheetContent($0) // << activate state passed here !!!
}
}
@ViewBuilder
private func sheetContent(_ state: ContentViewSheets.State) -> some View {
switch state {
case .aSheet:
Text("I'm the right sheet!")
default:
Text("Oops! I'm not supposed to show up!")
}
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With