2

I'm trying to figure out Core Data. I've been following some different tutorials and they all do things a bit differently.

I have a CoreDataStack and it's initialized in SceneDelegate

lazy var coreDataStack = CoreDataStack(modelName: "model")

I believe I then use dependency injection? to set a corresponding property in the viewControllers

guard let tabController = window?.rootViewController as? UITabBarController,
      let viewController = navigationController.topViewController as? ViewController else {
    fatalError("Application storyboard mis-configuration. Application is mis-configured")
}
viewController.coreDataStack = coreDataStack
viewController.context = coreDataStack.ManagedObjectContext

My questions is should I pass the entire coreDataStack object to the next view? Or just the context?

Initially I was passing the entire coreDataStack, Everything seemed to work just fine. But I wasn't sure if that was correct since most tutorials seem to only reference the context. (But even then, most tutorials are vastly different, even when they are made by the same author.)

import UIKit
import CoreData

class CoreDataStack {
    
    private let modelName: String
    
    
    init(modelName: String) {
        self.modelName = modelName
        setupNotificationHandling()
    }
    
    lazy var managedContext: NSManagedObjectContext = {
        return self.storeContainer.viewContext
    }()
    
    private lazy var storeContainer: NSPersistentContainer = {
        
        let container = NSPersistentContainer(name: self.modelName)
        container.loadPersistentStores { (storeDescription, error) in
            if let error = error as NSError? {
                print("Unresolved error \(error), \(error.userInfo)")
            }
        }
        return container
    }()
    
    
    // MARK: - Notification Handling
    
    func saveForDidEnterBackground() {
        saveContext()
    }
    
    @objc func saveChanges(_ notification: Notification) {
        saveContext()
    }
    
    // MARK: - Helper Methods
    
    private func setupNotificationHandling() {
        let notificationCenter = NotificationCenter.default
        notificationCenter.addObserver(self,
                                       selector: #selector(saveChanges(_:)),
                                       name: UIApplication.willTerminateNotification,
                                       object: nil)
    }
    
    // MARK: -
    
    private func saveContext() {
        guard managedContext.hasChanges else { return }
        
        do {
            try managedContext.save()
        } catch {
            print("Unable to Save Managed Object Context")
            print("\(error), \(error.localizedDescription)")
        }
    }
    
}
StonedStudio
  • 507
  • 3
  • 20
  • 1
    It depends on what do you want to do in your vc. Generally I recommend using a *temporary* context for saving data and the main context for reading only - see [Accessing Core Data Stack in MVVM application](https://stackoverflow.com/q/61571960/8697793). Then you might want to pass the whole CoreDataStack as the main context may not be enough. – pawello2222 Sep 27 '20 at 21:53
  • So it really doesn't matter if you pass the `coreDataStack` or just the `context`? I found out about child contexts yesterday so I was refactoring to remove the coreDataStack, but I eventually ran into a case where I was segueing to one of the mainVCs in the tab bar that was requiring the whole stack... Which led to further confusion. – StonedStudio Sep 27 '20 at 22:03
  • 1
    Again, it depends on what you really want to do in your vc - whether it's just fetching or something more. You can also take a look at some *Spring-style* Dependency Injection with property wrappers - an example can be found [here](https://stackoverflow.com/a/61753047/8697793). – pawello2222 Sep 27 '20 at 22:56
  • I don’t really know what I’m doing. Which is why I’m curious to hear what the benefits of passing the context rather than the entire `coreDataStack`. - Each tabs rootVC is a FRC. They then go to a detail view of the object. (Which can be edited), or they add a new object. (Both of which use a child context). Then inside the detail, there’s a few other VCs that go deeper and can add/edit other details. Also using child contexts. – StonedStudio Sep 28 '20 at 03:20
  • 1
    If your app is simple and your core data usage is simple then you might just use one context and you can pass it around instead of the your stack class, why make it harder right? But for larger apps or more complicated use-cases you might want to work with different contexts as mention earlier and then you need the stack class for this. I guess there is no clear cut right or wrong here but if you use the stack class even for a simple app you get used to it and you can re-use it and your knowledge for future apps. – Joakim Danielson Sep 28 '20 at 09:22
  • I see. I’ll go back to using the whole stack class then. It seems like overall, it’s easier to use as well since you also get access to the saving method through it. – StonedStudio Sep 28 '20 at 16:06

0 Answers0