Sheet sees the variable change from the second time

Hi everybody, after updating to 14 iOS ran into a problem. When calling Sheet, there is a later update of the variable from the second time. I will give an example:

Code Block
@State var showTestSheet : Bool = false
@State var testVar : Bool = false
Button(action:
{
self.testVar.toggle()
self.showTestSheet = true
}) {
Text("Test")
}
.sheet(isPresented: self.$showTestSheet, content: {
if(self.testVar) {
Text("True")
} else {
Text("False")
}})

The first time the button is clicked, the testVar variable changes, but inside sheet it is not changed. When you press the button again, everything works as expected. On iOS 13 everything works without errors. Maybe I'm doing something wrong or I missed the information that something has changed. If anyone comes across, help or tell me where to look. Very grateful in advance for any answer.

Accepted Reply

There are several reports which say @State variables do not work as expected in sheet.

This is one of them.
Issue with .sheet() Passing String to a View in SwiftUI 2.0

In my opinion, this is a bug of the current implementation of SwiftUI. You should better send a feedback to Apple.


But, iOS 14 is released with this bug unfixed, so we need some workaround.

One way is:
  • Pass a Binding instead of the value of the @State variable

  • Use the value of the Binding in the body of the view included in the sheet

Code Block
import SwiftUI
struct ContentView: View {
@State var showTestSheet : Bool = false
@State var testVar : Bool = false
var body: some View {
Button(action: {
self.testVar.toggle()
self.showTestSheet = true
}) {
Text("Test")
}
.sheet(isPresented: self.$showTestSheet) {
TestSheetView(testVar: self.$testVar)
}
}
}
struct TestSheetView: View {
@Binding var testVar: Bool
var body: some View {
if self.testVar {
Text("True")
} else {
Text("False")
}
}
}

There may be another better way, but this one works as expected as far as I tested.

Replies

There are several reports which say @State variables do not work as expected in sheet.

This is one of them.
Issue with .sheet() Passing String to a View in SwiftUI 2.0

In my opinion, this is a bug of the current implementation of SwiftUI. You should better send a feedback to Apple.


But, iOS 14 is released with this bug unfixed, so we need some workaround.

One way is:
  • Pass a Binding instead of the value of the @State variable

  • Use the value of the Binding in the body of the view included in the sheet

Code Block
import SwiftUI
struct ContentView: View {
@State var showTestSheet : Bool = false
@State var testVar : Bool = false
var body: some View {
Button(action: {
self.testVar.toggle()
self.showTestSheet = true
}) {
Text("Test")
}
.sheet(isPresented: self.$showTestSheet) {
TestSheetView(testVar: self.$testVar)
}
}
}
struct TestSheetView: View {
@Binding var testVar: Bool
var body: some View {
if self.testVar {
Text("True")
} else {
Text("False")
}
}
}

There may be another better way, but this one works as expected as far as I tested.
Thank you very much for your reply. Your solution works.
[Edited]
I'm having the same problem. I tried your work around and it didn't work.
Basically I get a blank sheet the first time you tap on an item, but if I dismiss the blank sheet (swipe down) and tap again, it has the information in it.

Interestingly enough: I tried your code with the test variable and it shows up correctly the first time, and then false the second time?

So I have it set to show "Hello World" if TestVar is true and "Failed" if TestVar is false-- the first tap shows "Hello World" and the second "Failed"?

?

I'm having the same problem. I tried your work around and it didn't work. 

Better start your own thread with enough code to reproduce your issue.
Thank you so much. I've been fighting with this for a few days until I figured out it was the sheet that was causing the problem. I thought it was something weird because I was setting the state in onOpenURL(perform:).