I’m trying to get my head around NSManagedObjectContext for Core Data. Xcode 10.1 provides a fair amount of boilerplate if the Core Data checkbox is selected when creating a new project. But I find it a bit confusing wrt how the current context is set for each view controller. I think I have a better way and am looking for advice to confirm, or to put me back on the right track.
For example, in the boilerplate AppDelegate code, didFinishLaunchingWithOptions provides the context to the MasterViewController like this:
let masterNavigationController = splitViewController.viewControllers[0] as! UINavigationController
let controller = masterNavigationController.topViewController as! MasterViewController
controller.managedObjectContext = self.persistentContainer.viewContex
In the MasterViewContoller, the first use of context picks it up from the fetchedResultsController AND there is code to save the context provided, even though the AppDelegate already has a saveContext() function available to do the same thing:
@objc
func insertNewObject(_ sender: Any) {
let context = self.fetchedResultsController.managedObjectContext
let newEvent = Event(context: context)
// If appropriate, configure the new managed object.
newEvent.timestamp = Date()
// Save the context.
do {
try context.save()
} catch {
// Replace this implementation with code to handle the error appropriately.
// fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
let nserror = error as NSError
fatalError("Unresolved error \(nserror), \(nserror.userInfo)")
}
}
In my app with multiple view controllers I have made mistakes trying to re-declare or hand off the context in each one where it’s needed, so had to contend with errors that were caused by inadvertently having more than one context flying around.
So my question is this: Am I making a mistake, or is there some downside to the following approach:
1) Make the AppDelegate a singleton:
class AppDelegate: UIResponder, UIApplicationDelegate, UISplitViewControllerDelegate {
var window: UIWindow?
static let shared = AppDelegate()
…
2) In each class where it’s needed, always define the context (I’m assuming I only need one) like this:
let context = AppDelegate.shared.persistentContainer.viewContext
3) Whenever the context needs to be saved, do it like this:
AppDelegate.shared.saveContext()
That seems much simpler, clearer and less prone to errors, and seems to work in my implementation. Are there problems with this that I'm not seeing?