SwiftUI and SwiftData @Query

Hey everyone,

I’m relatively new to SwiftUI and iOS development, having started earlier this year, and I’m working on a Notes app using SwiftData. I’ve run into some issues when dealing with nested views.

In my app, I’m using a SwiftData @Query in a parent view and then passing the model objects down the view tree. However, I’m frequently encountering errors such as “No container found” or similar. To work around this, I’ve tried having the child views perform their own SwiftData @Query, with the parent view passing a string identifier to the child views. This approach has helped somewhat, but I’m still not entirely sure how to properly manage UI updates.

Additionally, I’ve noticed that turning on iCloud syncing seems to have made the problem worse. The errors have become more frequent, and it’s unclear to me how to handle these situations effectively.

Could someone explain the best practices for handling SwiftData queries in nested SwiftUI views, especially with iCloud syncing enabled? Any guidance or feedback would be greatly appreciated.

Thank you!

You actually shouldn't be passing whole objects into child Views and instead only pass the params of the object that the View needs to do its job. If it needs write access to a property then you can convert the object to @Bindable and then pass in a binding to the property. This is one of the basic design principles of SwiftUI, "only pass in the data the View needs to do its job" [Data Essentials in SwiftUI WWDC 2020]

By the way, unfortunately you can't currently update @Query with a parameter passed in from a parent View because it is missing the ability to change the filter, e.g. it's missing something like:

    let somethingPassedIn: String

    let query = Query<Item, [Item]>
    var items: [Item] {
        query.filter = // change filter based on somethingPassedIn but impossible because query is missing the filter property
         return query.wrappedValue
    }

I know some developers try to re-init the @Query with a param from a parent but that is not the correct approach because these property wrappers are designed to be sources of truth and there is no guarantee they will update correctly if the init params change.

As a work around you could fallback to Core Data's @FetchRequest which does have the ability to dynamically change the query, e.g.

let fetchRequest = FetchRequest<Item>(sortDescriptors[])
var items: FetchedResults<Item> { 
    fetchRequest.predicate = // dynamically update it is possible
     return fetchRequest.wrappedValue 
}
SwiftUI and SwiftData @Query
 
 
Q