Jonah's answer really doesn't address the architectural issue with your code. Yes, he makes valid points about your presumptive casts, but honestly, if this is what your company is talking about when they say your code has "architecture issues", I'd be a little amazed.
The primary problem that sticks out to me is this:
etc.managedObjectContext = self.managedObjectContext;
I'm presuming that this code is not only in your app delegate, but it's also most likely in your didFinishLaunching
method.
So the questions become, how and why is the app delegate responsible for instantiating the managedObjectContext
in the first place? What view controllers outside the HSNEmployeesTableViewController
need to know about this object?
Can we not just instantiate this object in HSNEmployeesTableViewController
's viewDidLoad
method?
Code organization is very important. It's particularly important when you're working for a company or a group of coders where multiple people may be working in the same project and same source files. Nothing should have a scope any larger than is absolutely necessary. And objects should only be asked to do what makes sense for that object to do.
UITabBarController
is a tab bar controller. The primary function of the tab bar controller is to control the tab bar view and manage the view controllers in the different tabs.
UINavigationController
is a navigation controller. The primary function of the navigation controller is to control the navigation bar view and manage its navigation stack.
UIApplicationDelegate
is the application's delegate object. The primary function of this class is to manage application-level events. All the methods in this class relate to application-level events such as starting up, exiting, going to background, coming from background, responding to notifications while in background, etc. We should not put logic in the application delegate that is not pertinent on an application-level.
The didFinishLaunching
method is used to make a final few initializations that absolutely have to happen before your first view controller can be loaded.
Loading the data you want to present in the first view controller simply doesn't fit in this category.
You don't even have to worry about the casts, because your app delegate simply shouldn't need a reference to this view controller--the view controller can grab this data for itself.
As a pure critique of the posted code and ignore architecture issues, I offer this:
We can check the type of classes via isKindOfClass:
. Additionally, let's keep in mind that objectAtIndex:
can throw an out of bounds exception, but we only seem interested in index 0 in both cases, so let's use firstObject
, shall we?
UITabBarController *tvc;
if ([self.window.rootViewController isKindOfClass:[UITabBarController class]]) {
tvc = self.window.rootViewController;
}
UINavigationController *nvc;
if (tvc) {
nvc = [tvc.viewControllers firstObject];
}
HSNEmployeesTableViewController *vc;
if ([nvc isKindOfClass:[UINavigationController class]]) {
vc = [nvc.viewControllers firstObject];
}
if ([vc isKindOfClass:[HSNEmployeesTableViewController class]]) {
vc.managedObjectContext = self.managedObjectContext;
} else {
// something went wrong, handle it
}
Note that we will enter the else
no matter what step went wrong. If tvc
or nvc
ends up being nil
or not the kind of object we expect, we still get to the final if else
and it will return NO
and enter the else.
etc
controller it is working with however it's hard to demonstrate what a better implementation might look like without any context. Can you provide a more complete example of what class this is in and what it is responsible for? – Jonah Aug 13 '14 at 5:09managedObjectContext
as well as howself.managedObjectContext
is instantiated in the first place by the app delegate. – nhgrif Aug 13 '14 at 11:41