Question

I am totally stuck on this one. My basic problem is that my:

   - (NSFetchedResultsController *)fetchedResultsController

Method is crashing when it tries to read my Core Core entity, as the managedObjectContext / UIManagedDocument is nil. At the moment I think it is because my UIManagedDocument is not open / ready. So for the last 3 hours I have been trying to make it so my delegate method is not fired until the document is open.

This is the code that I am using to get the document:

      if (!self.document) {
    [[CATManagedDocumentHandler sharedDocumentHandler] performWithDocument:^(UIManagedDocument *document) {
        self.document = document;         
    }];
} 

This works fine at any other place in my app, but it seems as the opening process is just not quick enough for the delegate methods in my tableView.

Links I have looked at so far:

http://omegadelta.net/2011/05/10/how-to-wait-for-ios-methods-with-completion-blocks-to-finish/

Executing Code Block In Place Of @selector

About calling of dispatch_queue_t and dispatch_sync

Grand Central Dispatch (GCD) vs. performSelector - need a better explanation

GCD to perform task in main thread

iOS - how to be notified when a thread (using GCD) ends it's job

I have tried: Blocking main thread until I get NSNotification (set up in CATManagedDocumentHandler) & Blocking main thread until I get a block call back.

Neither of these work. My app just freezes. Am I think about this wrongly? How can I get the delegate method to wait until my document is open / ready? Or is there a different approach I should be taking with this?

Thanks

Carl.

Was it helpful?

Solution

ok, when your app first starts, I would suggest checking whether 1. your database exists (if it doesn't, you alloc init it) and 2. if the document doesn't exist (on disk), is closed or is open.

here's how you could do this:

looks like you are using a singleton for your database, so when your first view controller comes up, check whether the Managed Document has been alloc inited, so in ViewWillAppear:

if (!dataBase)
{
        NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
        url = [url URLByAppendingPathComponent:@"Your DB Name"];
        self.dataBase=[[UIManagedDocument alloc]initWithFileUrl:url];
}

so now if the database (UIManagedDocument) has been alloc inited, it still does not mean that the actual database file has been created on disk. You have to check for it as follows (and you could do this in a setter for your database or in ViewDidLoad, but don't do it in another thread because it won't work)

so you are checking for 3 cases here: does not exist

if (![[NSFileManager defaultManager]fileExistsAtPath:[yourManagedDocumentFromSingleton.fileUrl path])
{
   [[NSFileManager defaultManager]fileExistsAtPath:[yourManagedDocumentFromSingleton saveToUrl:[[NSFileManager defaultManager]fileExistsAtPath:[yourManagedDocumentFromSingleton.fileUrl forSaveOperation:UIDocumentSaveForCreating completionHandler: 
^(BOOL success){ now you can use your uidocument and its managed object context}];
    }

if file does exist but is closed:

else if (yourManagedDocumentFromSingleton.documentState==UIDocumentStateClosed)
{
[yourManagedDocumentFromSingleton openWithCompletionHandler:
^(BOOL success) {use your document here}];
}

finally if the document is already open, just use it:

else if (yourManagedDocumentFromSingleton.documentState=UIDocumentStateNormal)
{
//do whatever with the document
}

one important thing to mention is that UIDocument is not thread safe. So it must be used and checked in the same thread that it was created (presumably main thread here). Otherwise it will not work.

I don't know the exact structure of your view controller or singleton but if you follow these steps it will work.

PS. Also make sure that once your doc is up and running and you're adding items to it or removing, save it after each operation so your NSFetchedResultsController gets updated. CoreData does have autosave but I found that I had to manually save for things to work properly. You can save with (from previous method):

forSaveOperation:UIDocumentSaveForOverwriting
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top