Swift UI on iOS 14 not assigning new object to @State property

On iOS 13 I used to use optional @State properties to adapt views. In my case, the presented view would either create a new object (an assignment) if the state that is passed into it is nil, or edit the assignment if an assignment was passed in. This would be done in the action block of a Button and it worked beautifully.

On iOS 14 / Xcode 12 this no longer seems to work. Given the following code which creates a new assignment and passes it into the editor view when the user taps a "New Assignment" button, the value of assignment remains nil. Is anyone else experiencing similar behaviour?

Code Block Swift
struct ContentView: View {
@Environment(\.managedObjectContext) var context
@State var assignmentEditorIsPresented = false
@State var assignment: Assignment? = nil
var Body: some View {
[...]
Button("New Assignment", action: {
self.assignment = Assignment(context: context)
self.assignmentEditorIsPresented = true
})
.sheet(isPresented: assignmentEditorIsPresented) {
[...]
}
}
}

What's even weirder is that I tried adding a random piece of state, an Int, to this view and modifying it right before the assignment state (between lines 9 and 10) and it didn't change either.

Accepted Reply

Seems at this point to be a bug with Xcode 12 and the new framework. I was able to work around the issue by displaying the value of assignment in a View. I added the following code between lines 8 and 9 which fixed the issue and had the value updating properly:

Code Block Swift
Text("\(assignment?.description ?? "")"
.hidden()

I've sent in a bug report (FB7823148) through Feedback Assistant.
  • This will also work:

    let _ = assignment?.description

Add a Comment

Replies

Seems at this point to be a bug with Xcode 12 and the new framework. I was able to work around the issue by displaying the value of assignment in a View. I added the following code between lines 8 and 9 which fixed the issue and had the value updating properly:

Code Block Swift
Text("\(assignment?.description ?? "")"
.hidden()

I've sent in a bug report (FB7823148) through Feedback Assistant.
  • This will also work:

    let _ = assignment?.description

Add a Comment
I believe I am having this same issue (along with some others: https://developer.apple.com/forums/thread/652258) that are driving me mad, but seem to be bugs (code works perfectly in iOS 13.x like yours).

Your trick of using the object before assigning a value worked for me too! Thanks so much and thanks for filing the bug 👍🏾
Same here. Not fixed yet by Apple. Thanks for the workaround!
I thought I had the same problem in Xcode 12.0.1, where I updated a @State property without anything happening.

I then added some print-outs and found the problem to be even more bizarre than the UI not updating. I fetched data from an external api, decoded it and set the optional state to the result, but when I printed the non-nil state value in didSet, the value was printed as nil.

So, the @State property value didn't even seem to get applied, even though I set it to a non-nil value.

I then replaced @State with an @ObservableObject and got some interesting prints that @State didn't provide. It turned out that I wasn't performing the network completion on the main queue, which the observable object clearly printed out wasn't allowed.

After adjusting the code so the completion was performed on the main queue, everything started working, but the @State didSet still printed nil.
Thanks for the temporary solution! This was an annoying thing to debug 😅
After 3 months and the bug is still there!
Also seeing this bug, super frustrating ... Very neat hack though – thanks for your help!
Still seeing this bug on Xcode 12.4 on Catalina. Has anyone seen an update on it from Apple?


  • Same bug in Xcode 12.5. Super frustrating.

Add a Comment

The bug still here on Xcode 12.5.1.

Unfortunately the bug still there, I am working in Xcode 13.1 (13A1030d) and a @State property reminds being nil in this code:

struct ContentView: View {
  @State private var showDetailView = false
  @State private var selectedArticle: Article?
  
  var body: some View {
    NavigationView {
      List(articles) { article in
        ArticleRow(article: article)
          .onTapGesture {
            self.showDetailView = true
            self.selectedArticle = article
          }
      }
      .sheet(isPresented: self.$showDetailView) {
        // The self.selectedArticle property is nil
        if let selectedArticle = self.selectedArticle {
          ArticleDetailView(article: selectedArticle)
        }
      }
      .navigationBarTitle("Your Reading")
    }
  }
}

I could use the .sheet(item...) but I can storage a @State property and I don't know what is happening.

  • I'm doing the exact same thing. Bug is still there in 13.2.1.

Add a Comment

Still occurs in 13.3 :(

Duped radar FB9959325

FYI same issue still in xcode 13.4.1 - if it matters im presenting a sheet and the argument for that sheet is an object, which was initialized as a state object but empty. So i had it to default to a sample version of that object if the state object was nil (which it officially starts as), i even thought it was a racing issue since it was basically responding to a list item tap (so in the on tap gesture), i would set the value of that state object, then call the sheet, and in that i was printing the value of the object, it was accurate, but for whatever reason when the sheet took it it was nil so default kicked in, but if i tap on any other list item it works fine, so like the initial tap keeps it nil then it works, super weird. the workaround from @Theohhno works well but still bizarre, fyi im not a full blown dev just do enough to get by so may be missing something but either way thanks for the workaround

any update here? such a basic bug and as great as the fix it, it is a complete hack

I have the same problem. It seems the sheet modifier gets stuck to the initial value of a state property and gets rendered with it. Unless the parent view redraws, the sheet will stay stagnant no matter how the state property changes.