Cocoa Bindings with Storyboard woes

When using Core Data inside a Cocoa app (OS X – 10.10) much like an iOS app you will find that you need to pass around an instance of NSManagedObjectContext  between your view controllers. This becomes even more critical if you are using the native Cocoa Bindings ‘shortcuts’ to assign and manage your data to a table.

In my opinion documentation for dealing with Cocoa Bindings when using Storyboards is quite, shall we say ‘sparse’.  There are a few schools of thought on the best / easiest way to gain access to the App Delegate’s NSManagedObjectContext  needed by the NSArrayController :

Solution 1:

Use the NSManagedObjectContext  directly from the AppDelegate  from inside the View Controller.

This solution works great for simple usage, perhaps best used for single view controller apps, however there are some distinct disadvantages:

  • Could be seen as going against Apple’s guidelines
  • Code copy and paste – for every view controller these same lines of code need to be applied, this refers to the second block of code and assumes Solution 3 is not also used.
  • General code smell, it just feels/is wrong, it’s akin to a global variable. A better alternative would be to use Dependency Injection a.k.a solution >= 2.


Solution 2:

Inject the View Controller with the NSManagedObjectContext  from inside the AppDelegate .

This is a simple and clean approach, you are injecting the NSManagedObjectContext  into the ViewController  from the AppDelegate . Just a quick note for the getting the NSWindow  instance, Apple has this note:

The value in this property is nil when the app’s storyboard or nib file has not yet finished loading. It might also be nil when the app is inactive or hidden.

To combat this potential problem using something like  [[[NSApplication sharedApplication] windows] objectAtIndex:0];  should always return the first window.

Solution 3:

Now whilst the above two solutions successfully deal with allowing your root or 1st view controller access to an instance of the NSManagedObjectContext  object, what happens if you have more than one View Controller? One convenient method is to use  prepareForSegue  like so:

You must also add the property for the SecondViewController  (of course replace this for the real view controller name):

Now we are getting somewhere, we initially first inject the NSManagerObjectContext  into our first (root) view controller from the AppDelegate  and then pass this same context to our second view controller through the handy prepareForSegue function, awesome. However for each new view controller which requires the NSManagerObjectContext you will have to always do two things:

  1. Create the property managedObjectContext (to reference the NSManagerObjectContext ) in the view controller header file.
  2. Replicate the same logic in prepareForSegue which includes adding the header file for the controller the segue is going to

I don’t think doing the above is a major show stopper, I have seen some examples looping over all the view controllers within the NSWindow object and assigning the NSManagerObjectContext to each of them. To be honest I don’t much like the sound of this as it seems to go against ‘lazy loading’ which Apple seem keen to promote. No doubt these examples could be improved, but for now these options should provide a reasonable start point.