How to correctly manage the NSManagedObjectContext in each view controller?

I'm relative new with CoreData and I want to know if I'm doing the things right. First the documentation says:

"By convention, you get a context from a view controller. You must implement your application appropriately, though, to follow this pattern.

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

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

so what I do is 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 any place I want to do some change to the database I do this.

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 a different thread I have my custom method to create the NSManagedObjectContext with NSPrivateQueueConcurrencyType so it can be manage 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;
  • Is a good practice create a NSManagedObjectContext for each view controller where you will do some change to the database?
    1.1. It's a valid approach use [UIApplication sharedApplication] to get the persistent NSPersistentStoreCoordinator form the appdelegate?
  • It's safe to share the persistent store coordinator between the main thread and any other thread?
  • Any help will be appreciated :).


    I am going to disagree with most of the answers here. It is NOT bad for #1. In fact, it is probably good practice in most cases to do so. Especially if you have different threads running stuff. It has greatly simplified my apps to create NSManagedObjectContexts whenever needed including per view controller. This is also recommended by the guys behind MagicalRecord (which is what I use to make use of Core Data in most cases). NSManagedObjectContext creation is not a high overhead call per the MR guys. I am not a CoreData expert by any stretch of the imagination, but I have had much better results in doing it this way, as recommended to me by the MagicalRecord guys.


    I can only provide help for issue #1. The following is an example of what the Apple docs mean when they say pass the context to your view controllers. In this case, the app delegate is passing the context to the root view controller after the app delegate creates the context.

    // in AppDelegate.m (using storyboard)
    - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
    {
        // Override point for customization after application launch.
    
        // let's 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;
    }
    

  • No, it's not good to create NSManagedObjectContext for each controller. All you need is to have own context for each thread. So it depends on your logic. 1.1. Yes, it's not bad.
  • Yes, it is safe.
  • In my apps I use a singleton class with shared NSPersistentStoreCoordinator . And if I need to create new context, I use

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

    A bit detailed code snippet here. Usually my view controllers which use NSManagedObjectContext have table views, so I use NSFetchedResultsController . And I use only one shared context for all this controllers.

    Note 1: Some say it's a bad idea to have singletons.

    Note 2: Don't forget that you need to synchronize all your contexts via save and merge methods.

    链接地址: http://www.djcxy.com/p/16322.html

    上一篇: 指南针config.rb位置

    下一篇: 如何正确地管理每个视图控制器中的NSManagedObjectContext?