SwiftData Model class not triggering observation of computed property that depends on relationship

I created FB13074428 and a small sample project to demonstrate the bug. https://github.com/jamiemcd/Apple-FB13074428

Basically, if a SwiftData class is marked as @Model and it has a computed property that depends on a relationship's stored property, the computed property does not trigger updates in SwiftUI when the underlying relationship changes its stored property. This is Xcode 15 Beta 8.

@Model
final class Airport {
    var code: String
    var name: String
    var airplanes: [Airplane]
    
    init(code: String, name: String, airPlanes: [Airplane]) {
        self.code = code
        self.name = name
        self.airplanes = airPlanes
    }
    
    // Bug: This computed property is not triggering observation in AirportView when airplane.state changes. My understanding of the new observation framework is that it should.
    var numberOfAirplanesDeparting: Int {
        var numberOfAirplanesDeparting = 0
        for airplane in airplanes {
            if airplane.state == .departing {
                numberOfAirplanesDeparting += 1
            }
        }
        return numberOfAirplanesDeparting
    }
}

AirportView should update because it has Text for airport.numberOfAirplanesDeparting

struct AirportView: View {
    
    var airport: Airport
    
    var body: some View {
        List {
            Section {
                ForEach(airport.airplanes) { airplane in
                    NavigationLink(value: airplane) {
                        HStack {
                            Image(systemName: airplane.state.imageSystemName)
                            VStack(alignment: .leading) {
                                Text(airplane.name)
                                Text(airplane.type.name)
                            }
                        }
                    }
                }
            } header: {
                Text(airport.name)
            } footer: {
                VStack(alignment: .leading) {
                    Text("Planes departing = \(airport.numberOfAirplanesDeparting)")
                    Text("Planes in flight = \(airport.numberOfAirplanesInFlight)")
                    Text("Planes landing = \(airport.numberOfAirplanesLanding)")
                }
            }
        }
    }

Post not yet marked as solved Up vote post of jamiemcdaniel Down vote post of jamiemcdaniel
1.2k views

Replies

Update: The bug might not be with SwiftData or Observation framework, but rather in SwiftUI registering tracking for the observable.

If I add this to the body above I do get the view updating.

Section {
    Text("Planes departing = \(airport.numberOfAirplanesDeparting)")
    Text("Planes in flight = \(airport.numberOfAirplanesInFlight)")
    Text("Planes landing = \(airport.numberOfAirplanesLanding)")
}

And it updates the text in the footer as well.

But with only the 3 Text views in the footer SwiftUI will not update when the airport's computed properties change.

I encountered the same problem. Even without using a computed property, just working with airplane.state directly the views wouldn't register the changes. It seems to be related to SwiftData, because If you change your models to just @Observable classes all nested properties work as expected.

I am seeing this same issue. In my case the SwiftData modal's computed property will update the view correctly on the parent view but not on the grandparent view. Changing everything to @Observable classes works but is obviously not a solution for SwiftData.

Has anyone seen any progress/fixes for this?

I have a related (same?) issue. The symptom for me is that a computed var is not updating at all when I use it in a method in the view or in the model class itself.