Module 7 - error - nil is not a legal NSManagedObjectContext parameter searching for entity name 'ToDoEntity''

Hi guys,

I am using XCode 9.

I get this error that I’ve seen on the forum other people have, but they are all using older versions of XCode, when CoreData was creating different code in the AppDelegate.m

I’ve followed the videos in module 7 and I can’t figure out what I am missing…

This is the code from my AppDelegate.m:

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    ViewController *rootVC = (ViewController *)_window.rootViewController;
    rootVC.myContext = _persistentContainer.viewContext;

    return YES;
    }

#pragma mark - Core Data stack

@synthesize persistentContainer = _persistentContainer;

  • (NSPersistentContainer *)persistentContainer {
    // The persistent container for the application. This implementation creates and returns a container, having loaded the store for the application to it.
    @synchronized (self) {
    if (_persistentContainer == nil) {
    _persistentContainer = [[NSPersistentContainer alloc] initWithName:@“tableViewCoreData”];
    [_persistentContainer loadPersistentStoresWithCompletionHandler:^(NSPersistentStoreDescription *storeDescription, NSError *error) {
    if (error != nil) {
    // Replace this implementation with code to handle the error appropriately.
    // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.

                  /*
                   Typical reasons for an error here include:
                   * The parent directory does not exist, cannot be created, or disallows writing.
                   * The persistent store is not accessible, due to permissions or data protection when the device is locked.
                   * The device is out of space.
                   * The store could not be migrated to the current model version.
                   Check the error message to determine what the actual problem was.
                  */
                  NSLog(@"Unresolved error %@, %@", error, error.userInfo);
                  abort();
              }
          }];
      }
    

    }

    return _persistentContainer;
    }

#pragma mark - Core Data Saving support

  • (void)saveContext {
    NSManagedObjectContext *context = self.persistentContainer.viewContext;
    NSError *error = nil;
    if ([context hasChanges] && ![context save:&error]) {
    // Replace this implementation with code to handle the error appropriately.
    // abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
    NSLog(@“Unresolved error %@, %@”, error, error.userInfo);
    abort();
    }
    }

And this is from ViewController.m

@interface ViewController () <UITableViewDelegate, UITableViewDataSource, NSFetchedResultsControllerDelegate>

@property (weak, nonatomic) IBOutlet UITableView *tableView;

@property (weak, nonatomic) IBOutlet UITextField *textField;

@property (strong,nonatomic) NSFetchedResultsController *resultsController;

@end

@implementation ViewController

  • (void)viewDidLoad {
    [super viewDidLoad];

    // NSFetchedResultsController delegate
    NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];

    fetchRequest.entity = [NSEntityDescription entityForName:@“ToDoEntity” inManagedObjectContext:_myContext];

    fetchRequest.predicate = [NSPredicate predicateWithFormat:@“TRUEPREDICATE”];

    fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@“title” ascending:YES]];

    _resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_myContext sectionNameKeyPath:nil cacheName:nil];
    _resultsController.delegate = self;

    NSError *err;

    BOOL fetchSucceeded = [_resultsController performFetch:&err];

    if(!fetchSucceeded){
    @throw [NSException exceptionWithName:NSGenericException reason:@“Could’t fetch!” userInfo:@{NSUnderlyingErrorKey:err}];
    }

}

  • (IBAction)todoTapped:(id)sender {
    // Get the text
    NSString *text = _textField.text;
    NSManagedObjectContext *ctx = _myContext;

    // Store the text in a CoreData object
    ToDoEntity *item = [NSEntityDescription insertNewObjectForEntityForName:@“ToDoEntity” inManagedObjectContext:ctx];
    item.title = text;

    // Save the CoreData object
    NSError *err;
    BOOL saveSuccess = [ctx save:&err];
    if (!saveSuccess){
    @throw [NSException exceptionWithName:NSGenericException reason:@“Could’t save!” userInfo:@{NSUnderlyingErrorKey:err}];
    }
    else{
    _textField.text = nil;
    }
    }

#pragma mark - TableView Delegates

-(NSInteger) numberOfSectionsInTableView:(UITableView *)tableView{
return 1;
}

-(NSInteger) tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
return _resultsController.sections[section].numberOfObjects;
}

-(UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{

ToDoEntity *item = _resultsController.sections[indexPath.section].objects[indexPath.row];

TableViewCell *cell = (TableViewCell *) [tableView dequeueReusableCellWithIdentifier:@"TableCell" forIndexPath:indexPath];

[cell setTitle:item];
return cell;

}

#pragma mark - NSFetchedResultsControllerDelegate

-(void) controllerWillChangeContent:(NSFetchedResultsController *)controller{
[_tableView beginUpdates];
}

-(void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{

switch(type) {
        
    case NSFetchedResultsChangeInsert:
        [_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        break;
        
    case NSFetchedResultsChangeDelete:
        [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        break;
        
    case NSFetchedResultsChangeUpdate:{
        TableViewCell *cell = [_tableView cellForRowAtIndexPath:indexPath];
        ToDoEntity *item = [controller objectAtIndexPath:indexPath];
        [cell setTitle:item];
        break;
    }
    case NSFetchedResultsChangeMove:
        [_tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        [_tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                         withRowAnimation:UITableViewRowAnimationFade];
        break;
}

}

-(void) controllerDidChangeContent:(NSFetchedResultsController *)controller{
[_tableView endUpdates];
}

I tried to change some things here and there, but nothing worked…

I’m missing something and can’t figure out what.

Anybody has an idea?

Thank you,
Mircea

Hey guys,

I still haven’t found a solution, but I do get the same error with Module 8, as expected.

After searching more on internet I pinned it down to this: basically it fails at this line when the fetched is done ->
fetchRequest.entity = [NSEntityDescription entityForName:@“ToDoEntity” inManagedObjectContext:_managedObjectContext];

it means that namagedObjectContext is nil…

I don’t get it, because also in the previous post that is using myCOntext, that one gets initialized when the app is started…
here as well, it gets initialized in the AppDelegate at startup and then passed on using the Handles…

  • (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {

    id child = (id) _window.rootViewController;
    [child receiveMOC:_persistentContainer.viewContext];

    return YES;
    }

    • (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {

      id child = (id)[segue destinationViewController];
      [child receiveMOC:_managedObjectContext];

    }

    • (void) receiveMOC:(NSManagedObjectContext *)incomingMOC{

      _managedObjectContext = incomingMOC;

    }

    #pragma mark - NSFetchedResultsControllerDelegate

    -(void) initialiseNSFetchedResultsControllerDelegate {

      NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
      
      fetchRequest.entity = [NSEntityDescription entityForName:@"ToDoEntity" inManagedObjectContext:_managedObjectContext];
      
      fetchRequest.predicate = [NSPredicate predicateWithFormat:@"TRUEPREDICATE"];
      
      fetchRequest.sortDescriptors = @[[[NSSortDescriptor alloc] initWithKey:@"toDoTitle" ascending:YES]];
      
      _resultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:_managedObjectContext sectionNameKeyPath:nil cacheName:nil];
      _resultsController.delegate = self;
      
      NSError *err;
      BOOL fetchSucceeded = [_resultsController performFetch:&err];
      if(!fetchSucceeded){
          @throw [NSException exceptionWithName:NSGenericException reason:@"Could't fetch!" userInfo:@{NSUnderlyingErrorKey:err}];
      }
    

    }

I still haven’t figured it out why is it nil and how to fix it…

Any ideas are welcome.

Thanks,
Mircea

Is this site dead? Nobody seem to use it anymore…

I’m not able to finish my assignment for this week 4 and can’t finish the course if I’m not solving this problem…

I’ve been trying for days now, tried different things, tried to assign something to the managedObjectContext before is called with the fetch function…but nothing seems to work…

Professor Patterson doesn’t seem to login around here anymore…

I hope someone will help out soon, I find it hard to believe I’m the only one with this problem…

thanks,
Mircea

Well, guess what, I finally figured out what was wrong :smile:

As with XCode 8 and above, we have to use context like this:

NSManagedObjectContext *managedObjectContext = self.persistentContainer.viewContext;

instead of the old

NSManagedObjectContext *managedObjectContext = self.managedObjectContext;

But one very important thing, that I forgot to add, and because of that I had this error that took me all these days to debug and was driving me nuts :slight_smile:, is that you need to add this code:

[self persistentContainer];

Without this, the context will not be initialized, and it will always be nil, giving that error that I was getting all this time…

Hope it helps,
Mircea

1 Like

mate I totally feel you! This assignment drives me nuts and no activity on the site on top of no people checking the assignment. Good course but needs to be updated!

Mircea, can you point me in the right direction, please?

Where in the code do change it to = self.persistentContainer.viewContext

is it in the MyUINavigationController.m?

Thank you in advance mate!