Archive for April, 2009

Applying the last “tip”… and uncovering a new “mystery”!

My last post was on a way not to need to know when CoreData’s data is loaded, but rather “force” its load. I’m currently implementing this correction in my project, but in my way, I faced again something that may interest you.

So, my case is a bit specific, but every CoreData user is likely to face it one day or another…

Consider the following code:

[myArrayController fetchWithRequest:nil merge:YES error:&error];
NSManagedObjectContext *maoc1 = [(NSPersistentDocument *)[[NSDocumentController sharedDocumentController] currentDocument] managedObjectContext];
NSManagedObjectContext *maoc2 = [myArrayController managedObjectContext];

  • Assumes myArrayController is bound in InterfaceBuilder to the document’s managed object context.
  • Assumes your document does not contain any object of myArrayController‘s entity at this time, and that your goal is to create one.

You might thus do something like this:

[NSEntityDescription insertNewObjectForEntityForName:EntityNameFilter inManagedObjectContext:maoc2];

You probably noticed in the first code excerpt that I made two NSManagedObjectContext objects, from two different ways. In fact, if I do not use maoc2 in my second code excerpt, I end up with the following exception:
+entityForName: could not locate an NSManagedObjectModel for entity name 'EntityName'

I cannot explain this behavior at this time (since I was feeling maoc1 and maoc2 should be the same…), but it solved my problem… and might solve yours too! (hoping so).

Following the track of correctly managing CoreData-document loading

Since I’m debugging my project at this time, I am investigating deeper on the subject I previously wrote on (see this previous post: How to determine when CoreData’s data is loaded?). It did not take me much time to find something in Apple’s documentation (even if I never fell on it before):

Cannot access contents of an object controller after a nib is loaded

Problem: You want to perform an operation with the contents of an object controller (an instance of NSObjectController, NSArrayController, or NSTreeController) after a nib file has been loaded, but the controller’s content is nil.

Cause: The controller’s fetch is executed as a delayed operation performed after its managed object context is set (by nib loading)—the fetch therefore happens after awakeFromNib and windowControllerDidLoadNib:.

Remedy: You can execute the fetch “manually” with fetchWithRequest:merge:error:—see “Core Data and Cocoa Bindings.”

You can find this extract in the “Core Data Programming Guide”, “Troubleshooting Core Data” section (in Apple’s Mac OS X Developer documentation). It may be in previous versions of the documentation, but I currently use Leopard’s.

If I understand well Apple’s remedy, I should not try to wait my data to be loaded (and therefore find a way to know it), I should rather force the loading myself. So why not? I’ll try, and let you know if it works (and is fine) for me…

More on the “Cannot perform operation without a managed object context” exception

After applying the tip I explained in my last post, I was still having this “Cannot perform operation without a managed object context”. Simply googling it gave me the following link: Cocoabuilder – (Charilaos Skiadas) Cannot perform operation…

As a matter of fact, it answered my remaining problem. The solution is quite simple, since even if you managed the last tip (being sure CoreData loaded your document’s data before relying on it), you still need to have bound your array controllers with the managed object context…

How to determine when CoreData’s data is loaded?

Working for some time with CoreData’s concept in my Cocoa’s developments, I am for long disturbed by the feeling to be unable to determine when the data finished loading from the file. If this may not be a problem for simple applications, it begins to be a problem in my current project.

To be more concrete:

  1. Your application uses CoreData for saving data in documents.
  2. Suppose some classes of your application requires to perform actions during the loading of a document, but they also relies on the data provided by CoreData’s implementation (and saved in the document you’re opening).

At this point, I generally rely on the awakeFromNib: method to let my classes perform actions while the document is loading. However, it won’t work when you are in need of data managed by CoreData! The data is indeed being loaded “in the background”, without giving us much information to determine at which point the loading is done.

As an exemple, I tried one hour ago to perform a fetch request on [[[NSDocumentController sharedController] currentDocument] managedObjectContext] and obtained a painful error: Cannot perform operation without a managed object context.

So? How can I perform anything based on CoreData’s data during document loading if I am not even able to know when I will be authorized to perform fetch requests?

Again, at this point, my only wayaround is to set the class as an observer on the content property of any NSArrayController bound to the document’s managed object context and filled with CoreData’s data. This way the observeValueForKeyPath:… method will be raised when CoreData filled the array controller with data. And at this point, I can be sure that the managed object context and model are available. However, I can’t still be sure that all the data has been loaded (for this, I should verify that all my array controllers have been filled, and thus have an observer on the content property of each of them).

Most of this is based on my understanding of CoreData and Cocoa. This may not be considered as the Truth, but it may help you in some way if you are at the beginner level, just as me. If you are more than a beginner and that you have The solution of this problem, do not hesitate to relieve me of this burden, and post a comment!

%d bloggers like this: