Apply @ObservedObject to each (managed) object in List

In my SwiftUI project, I have a List, with each row representing a Core Data managed object, of entity Foo. Each row's View contains a ProgressView(), which I would like to have updated magically by binding to this property

@Published var doneness: Double

which I have added to class Foo. The Foo class itself conforms to ObservableObject, thanks to inheritance from NSManagedObject.

So, all the pieces are in place for SwiftUI magic to happen, except that I cannot figure out a syntax for wrapping the loop variable foo with @ObservedObject. This is, I believe, why my progress view is not updating – my body() getter does not get called as expected when a doneness value is updated.

The loop variable foo is declared in the ForEach, line 12. How can I make these observable objects?

I also tried to put the @ObservedObject wrapper on the array of foos, line 5, but the compiler did not like that either – Value of type 'FetchedResults<>' has no member 'wrappedValue'.

Code Block
@FetchRequest(entity: Foo.entity(),
sortDescriptors: [],
predicate: nil)
var foos: FetchedResults<Foo>
var body: some View {
NavigationView {
VStack {
...
}
List {
ForEach(foos) {foo in
HStack {
...
if let doneness = foo.doneness {
ProgressView(value:doneness)
}
}
}
}
}
}

Replies

I tried some more ideas, but still not working.

First of all, I added a dummy property to the "worker" object which does the work whose progress I need to display. The dummy property is published and observed by the List view, and updated every time any of the doneness values are updated. So now my body() method runs, and I also put the value of this dummy property and the value of foo.doneness in the title of each 'ProgressView'.

Result: Now my body() method runs whenever any progress is updated, and the value of the dummy property in each progress view's title updates as expected. But, although the foo.doneness values are definitely being updated (I print the new values to the console in the "worker"), the very same calls, foo.doneness, inside that body() method, as seen in the progress view's title, are stuck at 0.0. In other words, this body() is stuck at the initial value snapshot, definitely not observing any changes.

I also tried adding a willSet to Foo.willChange, manually sending objectWillChange as shown below, but this does not help either:

Code Block
@Published var doneness: Double = 0 {
    willSet {
        objectWillChange.send()
    }
}

Well, realizing that I am apparently on my own here, I devised a workaround. Instead of publishing progress values via the non-managed property doneness which I added to Foo, I removed that property and instead publish progress values via an Array property of the "worker" described in my previous post.

I suspect the problem is that, as has historically often been the case, NSManagedObject has some special behaviors which cause some customizations by subclasses to fail. In this case, it may be that NSManagedObject has a specialized publishing mechanism which excludes its usage by non-managed properties.