I was previously instantiating a UIManagedDocument
within the first view controller that appeared on screen (embedded in a navigation controller), setting the managedObjectContext
as a property on each controller that needed it, and passing the context via the prepareForSegue
methods. That worked, but I kept getting a periodic UIManagedDocument
objective C message send error (UIManagedDOcument _setInConflict
) when completely relaunching or activating the app from the background. Apparently a message was being sent to a deallocated
instance of UIManagedDoc
(ARC is enabled). I'm using storyboards.
After research, I saw the approach of opening or creating the UIManagedDocument
in the app delegate, and just passing the context from it to the first on-screen view controller. The document itself is declared as a file-level variable in the app delegate (code below), apparently this delays the "premature deallocation
" a bit. I get a context in the app delegate. That crash on relaunch has gone away, at least thus far.
The problem is I can't pass the context from the app delegate to the first initial view controller. The completion handler executes after the document is opened, but not until after I've attempted to set the app delegate's context as the initial view controller's context. I can pass to subsequent view controllers with the segue methods after I've gotten a valid context in the first view controller.
What's the proper way to wait until the document is opened and the app delegate's context has been set? I'm not sure if or how to nest completion handler blocks. The delay is very short, but it's causing the view controller's context to be set before there is one.
Also, is that code concerning the access between the root view controller (navigation controller) and my initial view controller correct? I'm asking about "nesting" completion handlers because putting it just before the RETURN statement didn't do it either.
@implementation AppDelegate{
UIManagedDocument *document;
}
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
// Override point for customization after application launch.
NSURL *url = [[[NSFileManager defaultManager] URLsForDirectory:NSDocumentDirectory inDomains:NSUserDomainMask] lastObject];
url = [url URLByAppendingPathComponent:@"Demo Document"];
document = [[UIManagedDocument alloc] initWithFileURL:url];
if (![[NSFileManager defaultManager] fileExistsAtPath:[url path]]) {
//create
[ document saveToURL:url
forSaveOperation:UIDocumentSaveForCreating
completionHandler:^(BOOL success) {
if (success) {
self.context = document.managedObjectContext;
NSLog(@"Database Ready");
}
}];
} else if (document.documentState == UIDocumentStateClosed){
//open
[document openWithCompletionHandler:^(BOOL success) {
if (success) {
self.context = document.managedObjectContext;
NSLog(@"Database Ready from Opened");
if (self.context) {
NSLog(@"got one");
//Here is the code that's just "stuck" out of place
UINavigationController *rootNavigationController = (UINavigationController *)self.window.rootViewController;
InitialVC *myViewController = (InitialVC *)[rootNavigationController topViewController];
// Configure myViewController
myViewController.context = self.context;
}
}
}];
} else {
//try to use
self.context = document.managedObjectContext;
}