I have based my app upon the Core Data Books example project Apple provide and I have made each cell a custom cell which which displays certain data, works magically.
However, now I am trying to add a second custom cell. It is a singular cell which will always be the first cell in the table, then all of the fetched results from core data go below that.
I have tried like so:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == 0)
{
static NSString *CellIdentifier = @"statsCell";
GuestStatsCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[GuestStatsCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
//Configure the cell.
[self configureStatsCell:cell];
return cell;
}
else
{
static NSString *CellIdentifier = @"guestCell";
customGuestCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
{
cell = [[customGuestCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
}
// Configure the cell.
[self configureGuestCell:cell atIndexPath:indexPath];
return cell;
}
}
Along with some other changes to try and get things working. A few problems.
Firstly, the view loads fine, I get my custom cell at index 0 and then my core data cells load up below that. First problem, the very first core data cell isn’t visible as its hidden behind my custom cell but if I tap it I do get the detail view for that core data entry. So I need to work out how I can stop it going behind that custom cell.
I have tried to remedy this, for example, it seems logical that this chunk:
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
id <NSFetchedResultsSectionInfo> sectionInfo = [[fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects];
}
So, this is only setting enough cells for the core data records and doesn’t account for that additional custom cell. So I try something as simple that this:
return [sectionInfo numberOfObjects] + 1;
Then this results in this line causing me to get a crash and index beyond bounds error:
GuestInfo *guest = [fetchedResultsController objectAtIndexPath:indexPath];
That line is from the configureCell method which setups the core data record cells. So Im pretty stumped as to what to do.
Next problem, when I edit an attribute of any core data record in the detail view, returning to the tableview my custom cell doesn’t show any changes. It displays stats to do with the core data info. Only the other cells get updated.
ANy help would be much appreciated, and if you need to see anymore code or need more explanation let me know.
EDIT:
More code as requested to help me. This is the NSFetchedController code.
- (NSFetchedResultsController *)fetchedResultsController
{
if (fetchedResultsController != nil)
{
return fetchedResultsController;
}
// Create and configure a fetch request with the Book entity.
NSFetchRequest *fetchRequest = [[NSFetchRequest alloc] init];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"GuestInfo" inManagedObjectContext:managedObjectContext];
[fetchRequest setEntity:entity];
// Create the sort descriptors array.
NSSortDescriptor *lastNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"lastName" ascending:YES];
NSSortDescriptor *firstNameDescriptor = [[NSSortDescriptor alloc] initWithKey:@"firstName" ascending:YES];
NSArray *sortDescriptors = [[NSArray alloc] initWithObjects:lastNameDescriptor, firstNameDescriptor, nil];
[fetchRequest setSortDescriptors:sortDescriptors];
// Create and initialize the fetch results controller.
NSFetchedResultsController *aFetchedResultsController = [[NSFetchedResultsController alloc] initWithFetchRequest:fetchRequest managedObjectContext:managedObjectContext sectionNameKeyPath:@"displayOrder" cacheName:@"Root"];
self.fetchedResultsController = aFetchedResultsController;
fetchedResultsController.delegate = self;
// Memory management.
//No releasing with ARC!
return fetchedResultsController;
}
/**
Delegate methods of NSFetchedResultsController to respond to additions, removals and so on.
*/
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller is about to start sending change notifications, so prepare the table view for updates.
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath {
UITableView *tableView = self.tableView;
switch(type) {
case NSFetchedResultsChangeInsert:
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self configureGuestCell:[tableView cellForRowAtIndexPath:indexPath] atIndexPath:indexPath];
[self.tableView reloadData];
break;
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
// The fetch controller has sent all current change notifications, so tell the table view to process all updates.
[self.tableView endUpdates];
}
I’m implementing the same function and using offset with indexPath @Toro’s solution work just fine. Don’t know if there is a better way or not here is my adjustment for those interested.
Add one extra row for my custom cell, my fetched result have no section so I this work just fine.
private method for adjust indexpath to retrieve right object from NsFetchedResultController.
Here are method that I apply
adjustedIndexPath: