Reputation: 225
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 Sheet
s 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.
Upvotes: 4
Views: 517
Reputation: 258345
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!")
}
}
}
Upvotes: 5