1
votes

The title question arises for me when working in many areas of the application: models, controllers, getters, setters, actions, etc. I have a Core Data document-based application and I constantly need to get a reference to the current NSMangedObjectContext object.

The current scenario involves a custom controller I made to handle "simulations" (this application simulates a particular kind of mathematical model.) There is a button called "Simulate" and it is bound to an action in the simulation controller. The simulation controller needs to get information from the current document i.e. information from the NSManagedObjects in the current managed object context.

The simulation controller is a subclass of NSObjectController which has a method called managedObjectContext but when I call that method, I get nil. I'm not sure why nil is returned but I do know that the controller is not acting on behalf of any managed objects. It's controlling the simulator, which is not a model in MVC. The controller is an interface between the views, models, and the simulator.

How do I get the NSManagedObjectContext that is storing NSManagedObjects for the currently open window? The currently open window has views showing information from objects in the context, and the simulation button is in this window's toolbar.

Update:

Well... thanks to TechZen for opening my mind a little... or maybe it was just taking a break and going to a BBQ...

For this particular scenario the answer is:

Bind the managed object context in Interface Builder to my controller (the controller was created in interface builder and then I changed the class to be my subclass of NSObjectController). This setting can be found in the Bindings Inspector under Parameters and is called Managed Object Context. I set it to bind to the File's Owner and the model key path to "managedObjectContext".

Then, the message "managedObjectContext" works within my controller just like:

[self managedObjectContext];

This, however, still doesn't fully answer my question because I'd also like to get a reference to a managed object context in a class method of a subclass of NSManagedObject. So if the simulation controller then creates a new NSManagedObject by calling a class method on my subclass of NSManagedObject, I'd like that method to have a reference to the context and create the object. And I do not want to pass the context to the method... I feel like the class methods should be able to get the context... I remember seeing code like:

[[NSApp delegate] managedObjectContext];

But this didn't work for me. But if it did, this would be an excellent solution becauxe NSApp is global and returns the current NSApplication instance.

Update:

Well, after a lot of reading and Googling... I discovered that I was just totally off the mark in the design of my application. Instead of having a simulation controller receive the click of the simulation button, I created a custom NSWindowController for that window and it receives the simulation button click event (a kind of IBAction). NSWindowControllers have a reference to the NSPersistantDocument, which has a reference to NSManagedObjectContext. And this custom window controller I wrote get's that NSManagedObjectContext and passes it to the simulation controller... and the world is filled with joy. Not sure how useful this is to others, since this question and answer are now littered with noise.

1
The simulation controller is a sub class of NSObjectController... which has a method called managedObjectContext. When I call that method, I get nil. I'm not sure why nil is returned, but I do know that the controller is not acting on behalf of any managed objects. It's controlling the simulator, which is not a model in MVC. The controller is an interface between the views, models, and the simulator. - Jason

1 Answers

3
votes

If you are using a Core Data document based application, then each document will be an instance of NSPersistentDocument which will have its own NSManagedObjectContext for just that single document.

You can get the context by:

NSManagedObjectContext *context=[aPersistentDocument managedObjectContext];

Update:

With a document based app, you don't have a single, central or master managed object context because each document has it's own wholly independent Core Data stack from the store to the context. You end up with as many context has you have open documents.

This contrast with a more database like design in which the entire app has only those stores and context defined when the app was coded. In that case, you may have only one context that is used everywhere in the app. In that case, you can park the context in the app delegate and access it from anywhere.

It's bad design to have a class or instance method in a NSManagedObject subclass that finds a context because this limits the flexibility of the use of the subclass. To do so the class would have to be wired into the structure of a specific app so the subclass could only be used in a specific design where it could find the context. If you changed anything about the location of the context or the use of the subclass, you would have to write it all over again.

I think you need to back out and rethink your design and decide if you want a document based app or a more database-like app. I would recommend reading:

Document-Based Applications Overview and NSPersistentDocument Core Data Tutorial