Search code examples
swiftcore-datasingletonnsmanagedobjectcontext

How do I save the correct NSManagedObjectContext without using a singleton?


In my app, I moved the Core Data stack out of AppDelegate and into its own class called LiftEventDataManager. There are a few classes in which I get a reference to this stack and, of course, each time I do a new NSManagedObjectContext is created. These references are used to do things like pull some default application data from the db to present in a view (e.g. a list of the user's choices).

When the initial viewController is presented, my viewModel asks my LiftEventDataManagerfor a new object to back the view. The user's input is used to set the properties of this object and when they're done, I want to save the object. However, the object isn't being saved.

When the user taps save, the viewModel uses its reference to LiftEventDataManager and calls this function (Swift 2.3):

func saveLiftEvent() {
  do {
    try moc!.save()
        } catch {
            let saveError = error as NSError
            print("\(saveError), \(saveError.userInfo)")
        }
  NSNotificationCenter.defaultCenter().postNotificationName("LiftEventDidSave", object: nil)
}

I believe the object is not being saved because it was created by my viewModel asking the LiftEventDataManager for a new object which would have a managedObjectContext, but the save is called being by the LiftEventDataManager that I presume is getting a new reference to the Core Data stack. I suppose I could get the object's managedObjectContext with:

let moc = newLiftEvent.managedObjectContext

and then pass it to the saveLiftEvent(moc: NSManagedObjectContext).

Have I answered my own question about how to save it properly or is there a flaw in my design? Keep in mind please that I don't want to use a singleton.


Solution

  • You'll need to have some way of passing the NSManagedObjectContext along. A singleton is one way to do it, but it certainly isn't the only way to do it.

    It sounds like you're creating a new instance of LiftEventDataManager every time you need one. Instead of creating a new instance, can you pass along the existing instance using dependency injection of some sort?

    If the view model has a reference to the data manager, that might be a good place to centralize things without making a singleton.