So, I want to have a Text
that changes its content based on the contents of my CoreData Model. To do that I used a computed property in Xcode beta 4 but it doesn't seem to work anymore. Either that's a bug or there is some other issue I don't see?
The problem I have exactly is that my View (and the computed property) don't seem to get updated when self.objectWillChange.send()
is called in my store.
I also tried to 'export' my var into the store and get it from there, with the same result...
EDIT:
I just tried the same with another class and it didn't work with just objectWillChange.send()
but only with @Published
however, even that stopped working if the class inherited from NSObject...
I just found out: with
struct Today: View {
@EnvironmentObject var myStore: DateStore
var hasPlans: Bool {
guard let plans = myStore.getPlans() else { return false }
return plans.isEmpty
}
var body: some View{
VStack{
Text(hasPlans ? "I have plans":"I have time today")
Button(action: {
self.myStore.addPlans(for: Date())
}) {
Text("I have plans")
}
}
}
class DateStore: NSObject, ObservableObject, NSFetchedResultsControllerDelegate {
private var fetchedResultsController: NSFetchedResultsController<DateStore>
//...
public func addPlans(for date: Date){
//{...}
if let day = self.dates.first(where: { $0.date == date}){
day.plans += 1
saveChanges()
}else{
self.create(date: dayDate)
}
}
func controllerDidChangeContent(_ controller: NSFetchedResultsController<NSFetchRequestResult>) {
self.objectWillChange.send()
}
}
That's a very simplified version of my problem and I know that my DataModel works because the values change and self.objectWillChange.send()
is called, but my View isn't updated for some reason....
I don't see that NSObject is the source of the problem. The problem seems to be that you haven't implemented objectWillChange
. The compiler will let you get away with that, but the result is that your objectWillChange
does nothing.
Here's a simple example that shows how to configure an ObservableObject (that is an NSObject) with a computed property whose binding works:
class Thing : NSObject, ObservableObject {
let objectWillChange = ObservableObjectPublisher()
var computedProperty : Bool = true {
willSet {
self.objectWillChange.send()
}
}
}
struct ContentView: View {
@EnvironmentObject var thing : Thing
var body: some View {
VStack {
Button(self.thing.computedProperty ? "Hello" : "Goodbye") {
self.thing.computedProperty.toggle()
}
Toggle.init("", isOn: self.$thing.computedProperty).frame(width:0)
}
}
}
You can see by tapping the button and the switch that everything is live and responsive to the binding within the view.