Update data in CoreData and its value in a view

Viewed 55

I am new to developing in Swift and CoreData. I've been struggling with the following code which displays a view with some information on a student which is stored with CoreData. The button "Ask question" which is displayed in the view updates student.questionAskedClass but the view does not updates its value.

The value is clearly updated internally because if I relaunch the application, I can see that the value has been updated. But I would like to see it updated live.

Thanks for your help, Francois

import SwiftUI

struct StudentView: View {
  @Environment(\.managedObjectContext) var managedObjectContext

  var student: Student

  var body: some View {
    VStack(alignment: .leading) {
      Text("\(student.firstName)").font(.headline).foregroundColor(Color.black)
      Text("\(student.lastName)").font(.headline).foregroundColor(Color.gray)
      Spacer().frame(height: 10)
      Text("\(student.email)").font(.headline).foregroundColor(Color.gray)
      Spacer().frame(height: 10)
      Text("Number of questions asked: \(student.questionAskedClass)").font(.headline).foregroundColor(Color.gray)
      Button(action: {
        self.askQuestion()
      }) {
        Text("Ask question")
      }
    }
  }

  func askQuestion() {
    self.managedObjectContext.performAndWait {
      self.student.questionAskedClass += 1
      try? self.managedObjectContext.save()
    }
  }
}
2 Answers

All you need is

struct StudentView: View {
  @Environment(\.managedObjectContext) var managedObjectContext

  @ObservedObject var student: Student     // << here !!

Tested with Xcode 11.4 / iOS 13.4

You are changing a property of one of your CoreData object. However, that won't refresh the view as you only use on person instance to display the data. You will need to refresh the view, to display the update.

Just use a dummy @State, which you will toggle after changes.

@State var updateView : Bool = false

You will need to use it inside your view, so just add it somewhere:

  Text("\(student.firstName)" + (self.updateView ? "" : "").font(.headline).foregroundColor(Color.black)

And then toggle it:

Button(action: {
    self.askQuestion()
    self.updateView.toggle()
}) {
    Text("Ask question")
}
Related