Passing a ManagedObjectContext to view controllers using a storyboard with a root UITabBarController

With the storyboard, you do not have easy access to the first view controller in appDelegate (although as soon as you do prepareForSegue , it’s easy for you to pass ManagedObjectContext to the navigation stack.

I decided to provide each view controller (or a superclass of each view controller), requiring that Core Data access the moc member:

 @synthesize moc = _moc; @property (nonatomic) __weak NSManagedObjectContext *moc; 

I am worried about this because it is not a very elegant way to do this - too much code. But assignment directly requires specifying absolute indices in viewControllers arrays and changing appDelegate every time the requirement for ManagedObjectContexts changes

 - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UITabBarController *tabBarController = (UITabBarController *)self.window.rootViewController; // rootView gets a tab bar controller for(UINavigationController *navController in tabBarController.viewControllers) { for(UIViewController *viewController in navController.viewControllers) { if([viewController respondsToSelector:@selector(setMoc:)]) { [viewController performSelector:@selector(setMoc:) withObject:self.managedObjectContext]; NSLog(@"Passed moc to %@", [viewController description]); } } } return YES; } 

What are the pitfalls of this approach and is there a better way? Better to try and be more general:

 - (void)assignManagedObjectContextIfResponds:(UIViewController *)viewController { if([viewController respondsToSelector:@selector(setMoc:)]) { [viewController performSelector:@selector(setMoc:) withObject:self.managedObjectContext]; NSLog(@"Passed moc to %@", [viewController description]); } } - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { NSMutableArray *viewControllers = [NSMutableArray array]; UIViewController *firstLevelViewController = self.window.rootViewController; if([firstLevelViewController respondsToSelector:@selector(viewControllers)]) { NSArray *firstLevelViewControllers = [firstLevelViewController performSelector:@selector(viewControllers)]; for(UIViewController *secondLevelViewController in firstLevelViewControllers) { if([secondLevelViewController respondsToSelector:@selector(viewControllers)]) { NSArray *secondLevelViewControllers = [secondLevelViewController performSelector:@selector(viewControllers)]; for(UIViewController *thirdLevelViewController in secondLevelViewControllers) { [viewControllers addObject:thirdLevelViewController]; } } else { [viewControllers addObject:secondLevelViewController]; } } } else { // this is the simple case, just one view controller as root [viewControllers addObject:firstLevelViewController]; } // iterate over all the collected top-level view controllers and assign moc to them if they respond for(UIViewController *viewController in viewControllers) { [self assignManagedObjectContextIfResponds:viewController]; } return YES; } 
+6
source share
2 answers

Adam,

While I was studying storyboards, I pretty much did it the same way you did, except that I made each of my view controllers for which the MOC property was protocol-compatible.

There is nothing substantial, so I will move on.

I believe this is a storyboard, IMO, half baked. Based on the .Net background, it is obvious that there is no infrastructure for the object builder in combination with the IoC container. When Apple adds, Storyboards will be awesome. When the storyboard frame can look at the destinationViewController, determining its dependencies and solving the problem of the container’s life will be great. For now, all he really can do is look at the destinationViewController and initialize a generic option that has limited use.

Unfortunately, due to the fact that this is a semi-whitened solution, which I follow the traditional approach at the moment, that’s why all my view controllers are alloc'd and init'd manually, and more importantly, I added a method to each view controller initWithMOC: (MOC *) moc;

The architect in me tells me that this code is more reliable, I think it is a matter of opinion on whether a compromise is worth it.

Has anyone come up with a better way?

CA.

+2
source

I don’t know if I understood correctly, but why don’t you leave the context of the managed object directly in the AppDelegate class and leave all the logic for creating the instance there. And from now on you can ask for it.

 @property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext; 

then you can remember it anytime from anywhere.

 NSManagedObjectContext *moc = [(YourApplicationDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext]; 

For convenience, I declared a definition for it:

 #define MOC [(YourApplicationDelegate*)[[UIApplication sharedApplication] delegate] managedObjectContext] 

Therefore it becomes:

 [MOC save:&error]; 

You can take it wherever you want. Just try to look at the automatically generated code for the CoreData application in Xcode, you will see that many accessors with CoreData are there, and CoreData itself is lazily initialized from the first request.

+4
source

Source: https://habr.com/ru/post/909512/


All Articles