问题
I have a basic problem synchronizing openWithCompletionHandler: (UIManagedDocument) with the main activities.
Situation: I have a singleton class managing a shared UIManagedDocument. This class provides one method which should deliver the document in a normal state (i.e. creates or opens it, whatever is neccessary). But because openWithCompletionHandler: does its main job asynchronously in the background my program should wait with setting up the fetchedResultsController until the document is really open. The "viewWillAppear" method (currently) produces no useful output when the database is not ready. Waiting would be ok for me, but getting notified probably would be the better way. Maybe viewWillAppear turns out not to be the right point to setupFetchedResultsController because not called in a runloop.
Is there a standard pattern to achieve this?
Bit more of background (not so important I assume) I am working on a little iOS 5.1 app involving a CoreData UIManagedDocument. I resembled the example from Lesson 14 from last fall's Stanford course in iTunes-U. Everything was working fine until I tried to put the handling of the UIManagedDocument away from the UITableViewController class into a seperate class handling my document. In the original version the FetchedResultsController was set up in the completion handler.
回答1:
I suggest following Justin Driscoll's excellent post on Core Data with a Single Shared UIManagedDocument.
You will find a complete writeup on UIManagedDocument singleton and an example on performWithDocument. Your fetchedResultsController setup code should really go in the performWithDocument:^{} block.
Also note that openWithCompletionHandler is not thread safe - concurrent invocations of performWithDocument while opening the document will cause a crash. The solution for me was non-trivial (and quite app-specific), so if you run into the same problem, I suggest you looking into UIDocumentStateChangedNotification which notifies document state changes and can be your synchronization point for multiple document openers.
Some snippet if you are interested,
First in MYDocumentHandler's init, setup an additional notification at the end:
[[NSNotificationCenter defaultCenter] addObserver:self
selector:@selector(documentStateDidChange:)
name:UIDocumentStateChangedNotification
object:self.document];
Then in performWithDocument, @synchronized (self.document) on the critical open/creation sections to make sure only one thread enters at a time, and block further threads until open/creation succeeds.
Finally add the following function:
- (void)documentStateDidChange:(NSNotification *)notification
{
if (self.document.documentState == UIDocumentStateNormal)
@synchronized (self.document) {
... unblock other document openers ...
}
}
As for block/unblocking threads, YMMV. I used a dispatch_semaphore_t along with some dispatch_queues to satisfy app-specific requirements. Your case could be as simple as waiting for completion or dropping other threads.
来源:https://stackoverflow.com/questions/9964571/ios5-1-synchronising-tasks-wait-for-a-completion