Reputation: 4404
I'm struggling with a Core Data concept and I need some clarification.
I'm using Storyboards and I have 2 view. The first view is embedded in a navigation controller, and the second view is just a UIViewController that comes from a modal segue. In AppDelegate I am passing the managedObjectContext to the first view using this code:
UINavigationController *nav = (UINavigationController *) self.window.rootViewController;
JobListTableViewController *jltvc = (JobListTableViewController *)[[nav viewControllers]objectAtIndex:0];
jltvc.managedObjectContext = self.managedObjectContext;
The problem is that now I need to also pass the managedObjectContext from AppDelegate to my second view, but I dont know how to get a hold of it. Doing this, just fails since there's no index 1:
AddJobsViewController *ajvc = (AddJobsViewController *)[[nav viewControllers]objectAtIndex:1];
I can't post a screenshot of my storyboard since I dont have enough stackoverflow reputation :(
Any help on this core data/delegation issue will be highly appreciated. Thank you.
Upvotes: 3
Views: 5454
Reputation: 232
My suggestion to you is that you don't pass the context from view controllers. Rather than that create a new context and fetch the entities from the new context. The downside of passing the same context is that if a same entity is modified in two different places, you have to manage the merge conflict. Context is like a scrap pad that can be used to either make changes and save or else discard the context if you don't want changes. So you can create a local context every time you want to modify the entities and either save or discard it depending on your needs and hence avoiding conflicts. what i prefer is a 3 tier system like this
-(NSManagedObjectContext*) backgroundMasterContext // this context is used to save data in core data
{
if(!_backgroundMasterContext) {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if(coordinator) {
_backgroundMasterContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[_backgroundMasterContext setPersistentStoreCoordinator:coordinator];
}
}
return _backgroundMasterContext;
}
-(NSManagedObjectContext*) mainContext // this context is a read only context which is used everytime you want to read the entities
{
if (!_mainContext) {
NSPersistentStoreCoordinator *coordinator = [self persistentStoreCoordinator];
if (coordinator) {
_mainContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSMainQueueConcurrencyType];
[_mainContext setParentContext:self.backgroundMasterContext];
}
}
return _mainContext;
}
-(NSManagedObjectContext*) createWriteContext // this context is used everytime you want to edit an entity
{
NSManagedObjectContext *newContext = [[NSManagedObjectContext alloc] initWithConcurrencyType:NSPrivateQueueConcurrencyType];
[newContext setParentContext:self.mainContext];
return newContext;
}
And for saving i call this method
- (void) saveAllWithContext:(NSManagedObjectContext*) writeContext
success:(DMSuccessBlock)success
failure:(DMFailureBlock)failure
{
BOOL b = NO;
NSError *error = nil;
if([writeContext hasChanges]) {
b=[writeContext save:&error];
if(b) {
NSManagedObjectContext *parentContext = [writeContext parentContext];
if(parentContext) {
[parentContext performBlock:^{
[self saveAllWithContext:parentContext success:success failure:failure];
}];
} else {
if(success)
success();
}
} else {
if(failure)
failure(error);
}
}
else {
if(success)
success();
}
}
This method updates main context and background master context.
Hope it helps :)
Upvotes: 0
Reputation: 9836
In your JobListTableViewController or AddJobsViewController, you can hold reference of AppDelegate like this.
#import "AppDelegate.h"
AppDelegate *app = (AppDelegate*)[[UIApplication sharedApplication] delegate];
jltvc.managedObjectContext = app.managedObjectContext;
Upvotes: 6