Last year I was working on an app which was using the Core Data framework as a persistent medium to the SQLite store. I was reluctant to use any SwiftUI property wrappers for Core Data in my app, because I wanted to structure the app in several layers and those property wrappers were only available inside the View. The app worked but it was a pain to make sure that everything in Core Data was synced with SwiftUI views.
SwiftUI team has provided us with APIs to make sure that SwiftUI and Core Data works seamlessly together. In this post, we will be building a small budget app using SwiftUI and Core Data. We will start by discussing our original approach of implementing the app, where we did not use any helpers provided by the SwiftUI frame. Later, we will look into a much simpler implementation, which uses SwiftUI Core Data property wrappers.
The complete app is part of my course MV Design Pattern in iOS — Build SwiftUI Apps Apple’s Way
OLD WAY — Manually Calling Fetch or Implementing NSFetchedResultsController
I started with creating view models for each of my view. This included
AddNewBudgetViewModel etc. Each view model that interacted with Core Data was passed CoreDataManager as a dependency. CoreDataManager contains all the code which is used to setup Core Data stack and also provide fetching and persistence capabilities. The implementation of BudgetCategoryListViewModel is shown below:
The main reason for adding a CoreDataManager as a dependency is that sometimes developers want to create different managers based on the environment. For Core Data I have seen developers creating in-memory databases and writing tests against it. I am not in favour of such approach. I personally don’t write tests against an in-memory database. Instead I would write tests against an actual database and then make sure that the database is destroyed after each test. Remember that the unit test is the isolation, not the thing under test.