What I'm trying to do: Get an NSFetchedResultsController to work for the first time to connect a UITableView to Core Data. I'm a newbie and really inexperienced, and I've followed Ray Wenderlich's Tutorial word to word.
The error:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+entityForName: nil is not a legal NSManagedObjectContext parameter searching for entity name 'Medicine''`.
What I tried: None of the other StackOverflow questions that I found (including this and this) have the an explanation, except for the second one which makes some sense. However, the method he mentioned is already written in my app delegate, which I imported in the TableViewController class I'm using.
What I'd greatly appreciate: An explanation of what I'm doing/what's gone wrong and how to fix it, rather than just the answer/correction.
#import "PMMedicinesTableViewController.h"
#import "PMAppDelegate.h"
#import "Medicine.h"
@interface PMMedicinesTableViewController ()
@property (nonatomic, strong) NSFetchedResultsController *fetchedResultsController;
@property (nonatomic, retain) NSManagedObjectContext *managedObjectContext;
@end
@implementation PMMedicinesTableViewController
@synthesize fetchedResultsController = _fetchedResultsController;
- (id)initWithStyle:(UITableViewStyle)style
{
self = [super initWithStyle:style];
if (self) {
// Custom initialization
}
return self;
}
- (void)viewDidLoad
{
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
// self.clearsSelectionOnViewWillAppear = NO;
// Uncomment the following line to display an Edit button in the navigation bar for this view controller.
// self.navigationItem.rightBarButtonItem = self.editButtonItem;
NSError *error;
if (![[self fetchedResultsController] performFetch:&error]) {
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
exit(-1); // Fail
}
}
- (NSFetchedResultsController *)fetchedResultsController {
if (_fetchedResultsController != nil) {
return _fetchedResultsController;
}
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription
entityForName:@"Medicine" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
NSSortDescriptor *sort = [[NSSortDescriptor alloc]
initWithKey:@"name" ascending:NO];
[fetchRequest setSortDescriptors:[NSArray arrayWithObject:sort]];
[fetchRequest setFetchBatchSize:20];
NSFetchedResultsController *theFetchedResultsController =
[[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest
managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil
cacheName:@"Root"];
self.fetchedResultsController = theFetchedResultsController;
_fetchedResultsController.delegate = self;
return _fetchedResultsController;
}
- (void)didReceiveMemoryWarning
{
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}
#pragma mark - Table view data source
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
// Return the number of sections.
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id sectionInfo =
[[_fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
- (void)configureCell:(UITableViewCell *)cell atIndexPath:(NSIndexPath *)indexPath {
Medicine *med = [_fetchedResultsController objectAtIndexPath:indexPath];
cell.textLabel.text = med.name;
cell.detailTextLabel.text = [NSString stringWithFormat:@"%@",
med.name];
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"medicineCellIdentifier" forIndexPath:indexPath];
// Set up the cell...
[self configureCell:cell atIndexPath:indexPath];
return cell;
}
Thanks in advance!
The error is telling you that self.managedObjectContext
is nil, which means that you haven't assigned a value to that property. Most likely you should have done this in whatever code created or loaded this view controller (e.g. in prepareForSegue:sender:
if you're using storyboards).