Reputation: 777
Im new with iPhone programming and for that matter CoreData. I was just wondering about some general practices and ways of doing things.
I am trying to add/load entities from CoreData to a UITableView. So in the AppDelegate I am loading an NSArray of entities (NSManagedObjects) on didfinishlaunchingwithoptions and populating the NSArray for my table view controller. In the table view controller it is then using the NSArray of NSManagedObjects to specify the cell view in the cellForRowAtIndexPath method.
Is this the best way to do this? Should I be using an array of NSManagedObjects to load this and manage that array with adds/deletes or should the fetch be looped through and populate a new class object that I created seperate to represent each object that each cell will contain?
I dont want to do more work than needed, but I dont want to do anything poorly either.
Please help, and thank you very much!
Upvotes: 1
Views: 2560
Reputation: 2930
Your app delegate should just pass its NSManagedObjectContext
to your table view controller, which then creates its own instance of NSFetchedResultsController
, a class that efficiently loads managed objects for display in a UITableView
and responds to changes in your object graph.
The "Master-Detail Application" Core Data project template in Xcode 4.2 uses this pattern. It's a good reference and starting point. Here's how the master table view controller lazily loads and configures its results controller:
- (NSFetchedResultsController *)fetchedResultsController
{
if (__fetchedResultsController != nil) {
return __fetchedResultsController;
}
// Set up the fetched results controller.
// Create the fetch request for the entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
// Edit the entity name as appropriate.
NSEntityDescription *entity = [NSEntityDescription entityForName:@"Event" inManagedObjectContext:self.managedObjectContext];
[fetchRequest setEntity:entity];
// Set the batch size to a suitable number.
[fetchRequest setFetchBatchSize:20];
// Edit the sort key as appropriate.
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"timeStamp" ascending:NO];
NSArray *sortDescriptors = [NSArray arrayWithObjects:sortDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Edit the section name key path and cache name if appropriate.
// nil for section name key path means "no sections".
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:self.managedObjectContext sectionNameKeyPath:nil cacheName:@"Master"];
aFetchedResultsController.delegate = self;
self.fetchedResultsController = aFetchedResultsController;
NSError *error = nil;
if (![self.fetchedResultsController performFetch:&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();
}
return __fetchedResultsController;
}
Once you have an NSFetchedResultsController
, it's just a matter of plugging the fetched objects into the table view data source methods, for example:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
UITableViewCell *cell = <#Get the cell#>;
NSManagedObject *managedObject = [<#Fetched results controller#> objectAtIndexPath:indexPath];
// Configure the cell with data from the managed object.
return cell;
}
Take a look at the project template and read both the NSFetchedResultsController class and NSFetchedResultsControllerDelegate protocol references to learn more. Apple's documentation includes a complete source code example.
Upvotes: 8