How to properly manage NSManagedObjectContext in each view controller?

I am relatively new with CoreData and I want to know if I am doing this correctly. The documentation first says:

“By convention, you get context from the view controller. You must implement your application accordingly, but follow this pattern.

When you implement a view controller that integrates with Core Data, you can add the NSManagedObjectContext property.

When you create a view controller, you pass it the context that it should use. You are transferring an existing context or (in a situation where you want the new controller to control a discrete set of changes), the new context that you create for it. Typically, it is the responsibility of the application delegate to create the context for the transition to the first view controller that is displayed. "
https://developer.apple.com/library/ios/documentation/DataManagement/Conceptual/CoreDataSnippets/Articles/stack.html

so I create a property for my NSManagedObjectContext:

MyViewController.H @interface MyViewController : ViewController { NSManagedObjectContext *moc; } @property (nonatomic, retain) NSManagedObjectContext *moc; @end MyViewController.m @implementation MyViewController @synthesize moc=moc; 

1. - And anywhere I want to add to the database, I do it.

 MainNexarAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; self.moc = [[NSManagedObjectContext alloc] init]; self.moc.persistentStoreCoordinator = [appDelegate persistentStoreCoordinator]; /*code**/ [self.moc save:&error]; 

2-. And if I'm going to work in another thread, I have my own method for creating an NSManagedObjectContext with NSPrivateQueueConcurrencyType so that it can be managed in a private queue:

  //Myclass NSObject<br> -(NSManagedObjectContext *)createManagedObjectContext{ MainNexarAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate]; NSPersistentStoreCoordinator *coordinator = [appDelegate persistentStoreCoordinator]; if (coordinator != nil) { __managedObjectContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType]; [__managedObjectContext setPersistentStoreCoordinator:coordinator]; } return __managedObjectContext; } //__managedObjectContext is my property from the .h file //@property (readonly,strong,nonatomic) NSManagedObjectContext* managedObjectContext; 
  • It is good practice to create an NSManagedObjectContext for each view controller, where will you make some changes to the database?
    1.1. Is this a valid approach that uses [UIApplication sharedApplication] to get a permanent NSPsistentStoreCoordinator from appdelegate?
  • Is it safe to share the persistent storage coordinator between the main thread and any other thread?

Any help would be appreciated :).

+7
ios objective-c core-data
source share
4 answers

I am going to disagree with most of the answers here. This is NOT bad for number 1. In fact, in most cases this is probably good practice. Especially if you have different threads. It greatly simplified my applications for creating NSManagedObjectContexts when necessary, including for each view controller. It is also recommended by the guys from MagicalRecord (which in most cases I use to use Core Data). Creating an NSManagedObjectContext is not a big overhead call for MR guys. I am not an expert on CoreData with any imagination, but I had much better results in this, as MagicalRecord guys recommended to me.

+1
source share
  • No, it is not recommended to create an NSManagedObjectContext for each controller. All you need is to have your own context for each thread. So it depends on your logic. 1.1. Yes, that’s not bad.
  • Yes, it is safe.

In my applications, I use a singleton class with a common NSPersistentStoreCoordinator . And if I need to create a new context, I use

 self.context = [NSManagedObjectContext new]; self.context.persistentStoreCoordinator = [[SharedStorage sharedStorage] storeCoordinator]; 

A detailed code snippet is here . Usually my view controllers that use NSManagedObjectContext have table views, so I use NSFetchedResultsController . And I use only one common context for all of these controllers.

Note 1: Some say it is a bad idea to have singlets.

Note 2: Do not forget that you need to synchronize all your contexts using the save and merge methods.

0
source share

I can provide assistance only for problem number 1. The following is an example of what Apple docs mean when they pass context to your controllers. In this case, the application delegate passes the context to the root view controller after the application delegate creates the context.

 // in AppDelegate.m (using storyboard) - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { // Override point for customization after application launch. // let assume that your MyViewController is the root view controller; grab a reference to the root view controller MyViewController *rootViewController = (MyViewController *)self.window.rootViewController; // initialize the Core Data stack... rootViewController.moc = ... // pass the context to your view controller return YES; } 
0
source share

Bad: create an NSManagedObjectContext for each viewController that is going to make some changes to the database Good: create a single NSManagedObjectContext aka singleton that will be passed to those who want to make some changes to the database, The consequence of this is that, since the application basically has one database, although you can have multiple databases in one application. Example1: Suppose you created a tab-based application, and the rootViewController of this window is UITabBarController, from the root you can get all the other controllers! and here you can pass context to them

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { /* MUNSharedDatabaseController is the singleton */ UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController; UIViewController *firstViewController = tabBarController.viewControllers[0]; firstViewController.managedObjectContext = [[MUNSharedDatabaseController sharedDatabaseController] managedObjectContext]; UIViewController *secondViewController = tabBarController.viewControllers[1]; secondVC.managedObjectContext = [[MUNSharedDatabaseController sharedDatabaseController] managedObjectContext]; // otherStuff, or etc. } 

There is also a great Core Data library, also known as MagicalRecord. You can check it out here: https://github.com/magicalpanda/MagicalRecord if you want to save time, this is really great, but it is not a replacement for Core Data. There is also an example of how to create a basic data syntax here: http://steamheadstudio.pl/wordpress/core-data-singleton-with-sample-code/

0
source share

All Articles