I’m trying to understand how and when the .sheet and .fullScreenCover initializers are called. Below is a minimal reproducible example, where the first screen has 3 colored rectangles and the SecondView (shown via .fullScreenCover) has 1 rectangle that changes color based on the selected color from the first screen.
- When the app first loads, the color is set to .gray.
- If I tap on the green rectangle, SecondView presents with a gray rectangle. (ie. the color DIDN’T change correctly).
- If I then dismiss the SecondView and tap on the red rectangle, the SecondView presents with a red rectangle. (ie. the color DID change correctly.)
So, I’m wondering why this set up does NOT work on the initial load, but does work on the 2nd/3rd try?
Note: I understand this can be solved by changing the ‘let selectedColor’ to a @Binding variable, that’s not what I’m asking.
Code:
import SwiftUI
struct SegueTest: View {
@State var showSheet: Bool = false
@State var color: Color = .gray
var body: some View {
HStack {
RoundedRectangle(cornerRadius: 25)
.fill(Color.red)
.frame(width: 100, height: 100)
.onTapGesture {
color = .red
showSheet.toggle()
}
RoundedRectangle(cornerRadius: 25)
.fill(Color.green)
.frame(width: 100, height: 100)
.onTapGesture {
color = .green
showSheet.toggle()
}
RoundedRectangle(cornerRadius: 25)
.fill(Color.orange)
.frame(width: 100, height: 100)
.onTapGesture {
color = .orange
showSheet.toggle()
}
}
.fullScreenCover(isPresented: $showSheet, content: {
SecondView(selectedColor: color)
})
}
}
struct SecondView: View {
@Environment(.presentationMode) var presentationMode
let selectedColor: Color // Should change to @Binding
var body: some View {
ZStack {
Color.black.edgesIgnoringSafeArea(.all)
RoundedRectangle(cornerRadius: 25)
.fill(selectedColor)
.frame(width: 300, height: 300)
}
.onTapGesture {
presentationMode.wrappedValue.dismiss()
}
}
}
struct SegueTest_Previews: PreviewProvider {
static var previews: some View {
SegueTest()
}
}
2
Answers
See comments and
print
statements. Especially thered
The problem is that you are not using your @State color inside SegueView, which will not reload your view on State change. Just include your @State somewhere in the code, which will force it to rerender at then update the sheet, with the correct color.
If you do not include your color state somewhere in the code, it won’t re render your SegueView, hence you still pass the old color gray to your
SecondView
.Or even pass your colors as Binding your your Second View..