SwiftData equivalent of NSFetchedResultsController

As far as I can tell, there’s no equivalent to Core Data’s NSFetchedResultsController in SwiftData. It would be very helpful to have a way to respond to sets of changes in a ModelContext outside of a SwiftUI view. For instance, this is very helpful when using a Model-View-ViewModel architecture. The @Query property wrapper is great for use in a SwiftUI view, but sometimes it’s helpful to process data outside of the view itself. The fetch() method on ModelContext is helpful for one-time operations, but as far as I can't tell it doesn't address receiving changes on an ongoing basis.

Am I missing some equivalent for this use case?

Also filed as feedback FB12288916

Post not yet marked as solved Up vote post of tschmitz Down vote post of tschmitz
990 views

Replies

Part 1: MVVM is not a great justification for the need of a NSFetchedResultsController

MVVM is discouraged when using SwiftUI. To a certain extent, SwiftUI Views are the ViewModels.

Assuming you use MVVM correctly, meaning that the lifecycle of your ViewModel is tied to the lifecycle of its related View, then MVVM should be replaced with MVVW, where VW stands for "ViewWrapper" (which is itself a View). Having a ViewWrapper should allow you to decouple the View from your model layer, hence allowing for View reusing and testing. To relate this comment to your question, you could use @Query in your "ViewWrapper" and pass your transformed data to your View.

Part 2: Can we justify the need for NSFetchedResultsController differently?

Yes. Allowing powerful usage of SwiftData with UIKit is the most obvious example. NSFetchedResultsController is all about tracking and diffing, which is built-in for SwiftUI. So building a NSFetchedResultsController for SwiftUI usage feels redundant. With this in mind, the fact that Apple didn't introduce NSFetchedResultsController is a rather telling proof that Apple built SwiftData for SwiftUI usage before all. It's not something they hide.

Part 3: Forgetting about the MVVM pattern, what about fetches that happen independently of Views lifecycles.

The tracking and diffing provided by NSFetchedResultsController is built to power views. It's not my opinion, it's Apple opinion. The documentation description says: "A controller that you use to manage the results of a Core Data fetch request and to display data to the user.". With this in mind, I think it's not needed/recommended to use NSFetchedResultsController in your data layer, repository layer, domain layer or wherever your business logic lives.

Conclusion:

My guess is that adoption of SwiftData will be slowed down drastically by its lack of compatibility with UIKit. And UIKit is not going anywhere. So, I assume Apple will eventually release a replacement for NSFetchedResultsController for the SwiftData world. But, if you use SwiftUI, the lack of NSFetchedResultsController should not be blocking you.

  • "MVVM is discouraged when using SwiftUI. To a certain extent, SwiftUI Views are the ViewModels."

    This is not a true and Apple has explained several times that SwiftUI views are not ViewModels. tschmitz Use case is a valid use case.

  • Wanting to isolate your query code from your pure UI code is a valid use case. Wanting to put the code in a class that is not a SwiftUI view is more arguable. Maybe saying SwiftUI View is your VM is controversial and mislead you away from my main point: View-composition (encouraged by Apple) can solve tschmitz issue.

Add a Comment