Asynchronous Initialisation of the Core Data Stack

If NSManagedObjectContext is nil then for some reason it has not been initialised yet.  

Remember that the Core Data stack gets initialised asynchronously and posts a message once it is ready to be used.  The OSCDStackmanager.openPersistentStore method, which is run on a background thread to avoid UI blocking issues if a long migration to a new model version is required, posts the OSStoreChangeNotification once the Core Data stack has been initialised.  

You should delay creating your viewControllers that access Core Data objects in them until you receive this notification or you should perform checks such as those below to determine when it is safe to access the managedObjectContext.

Your app should not be trying to access the managedObjectContext until it receives this message, so depending on your implementation you may have to check if the managedObjectContext is NIL before doing anything.  

In the MasterViewController I register for this notification

[[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(storeChanged) name:OSStoreChangeNotification object:nil];

and when I receive the  OSStoreChangeNotification notification then the viewControllers managedObjectContext gets set and the fetchedResultsController gets created.

-(void)storeChanged {
    FLOG(@"storeChanged called");
    _fetchedResultsController = nil;
    self.managedObjectContext = [[OSCDStackManager sharedManager] managedObjectContext];
    FLOG(@"managedObjectContext is %@",self.managedObjectContext);
    [self fetchedResultsController];
    self.detailViewController.detailItem = nil;
    [[self tableView] reloadData];

You will notice that in the viewController code I always check if the fetchedResultsController is NIL and then take the appropriate action.  For example in the UITableView I display the “Loading please wait…” message while things are being initialised by doing this

- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath
    if (self.fetchedResultsController == nil) {
        cell.textLabel.text = @"Loading please wait...";
        cell.accessoryType = UITableViewCellAccessoryNone;
        UIActivityIndicatorView *progressView = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
        cell.accessoryView = progressView;
        [progressView startAnimating];
    } else {
        cell.accessoryView = nil;
        NSManagedObject *object = [self.fetchedResultsController objectAtIndexPath:indexPath];
        cell.textLabel.text = [[object valueForKey:@"name"] description];
        cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;

Leave a Reply

Fill in your details below or click an icon to log in: Logo

You are commenting using your account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s