Reputation: 75
I have a tableview that is successfully incorporating an NSFetchedResultsController. However, I need the topmost cell in my tableview to read, "Add new object" and have UITableViewCellEditingStyleInsert instead of the default UITableViewCellEditingStyleDelete.
The FetchResultsController wants to check the managedObjectContext for objects--both to determine number of rows and to populate the table cells. The only way I can think to get around this is to create a dummy object, but I feel like there ought to be a more elegant solution.
For those who might be curious as to what solution I ended up with, I decided to have my insert cell at the bottom, not the top. Here is the relevant code:
- (void)viewDidLoad {
[super viewDidLoad];
// Uncomment the following line to preserve selection between presentations.
//self.clearsSelectionOnViewWillAppear = NO;
self.editing = YES;
self.tableView.allowsSelectionDuringEditing = YES;
self.tableView.delegate = self;
RubricAppDelegate *appDelegate = (RubricAppDelegate *)[[UIApplication sharedApplication] delegate];
managedObjectContext = [appDelegate managedObjectContext];
NSEntityDescription *entity = [NSEntityDescription entityForName:@"myClass" inManagedObjectContext:managedObjectContext];
NSFetchRequest *request = [[[NSFetchRequest alloc] init] autorelease];
[request setEntity:entity];
NSSortDescriptor *sortDescriptor = [[NSSortDescriptor alloc] initWithKey:@"classID" ascending:YES];
NSArray *sortDescriptors = [NSArray arrayWithObject:sortDescriptor];
[request setSortDescriptors:sortDescriptors];
[sortDescriptor release];
fetchedResultsController = [[NSFetchedResultsController alloc]
initWithFetchRequest:request
managedObjectContext:self.managedObjectContext
sectionNameKeyPath:nil cacheName:nil];
NSError *error;
[fetchedResultsController performFetch:&error];
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
NSLog(@"Number of sections = %d", [[fetchedResultsController sections] count]);
return 1;
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
// Return the number of rows in the section.
id <NSFetchedResultsSectionInfo> myClass = [[fetchedResultsController sections] objectAtIndex:section];
NSLog(@"Number of classes = %d", [myClass numberOfObjects]);
return ([[fetchedResultsController fetchedObjects] count] + 1);
}
// Customize the appearance of table view cells.
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
NSLog(@"FRC count + 1 = %d", ([[fetchedResultsController fetchedObjects] count] + 1));
if (indexPath.row == ([[fetchedResultsController fetchedObjects] count])) {
cell.textLabel.text = @"Add New Class";
}
else {
myClass *theClass = [fetchedResultsController objectAtIndexPath:indexPath];
NSLog(@"Class name is: %@", theClass.classTitle);
cell.textLabel.text = theClass.classTitle;
}
return cell;
}
- (UITableViewCellEditingStyle)tableView:(UITableView *)tableView editingStyleForRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.row == [[fetchedResultsController fetchedObjects] count]) {
return UITableViewCellEditingStyleInsert;
}
return UITableViewCellEditingStyleDelete;
}
The result (with some junk data):
Now my only issue is getting the delete functions to work properly. You can follow my post on that issue here
Upvotes: 1
Views: 2414
Reputation: 46718
Normally the add row is at the bottom.
You can accomplish this by changing the -tableView:numberOfRowsInSection:
and the -tableView:cellForRowAtIndexPath:
methods to adjust the cell count and adjust for it. So your -tableView:numberOfRowsInSection:
would return N+1 and your -tableView:cellForRowAtIndexPath:
would get object at N-1 unless N == 0 then it would return your "Add new object" cell.
There is no need to mess with the underlying Core Data elements as this is strictly a UI issue.
But now I'm not sure how to return the count of my fetched objects (assuming that is what I used for "N" in your above answer). Also, wouldn't I want -tableView:cellForRowAtIndexPath to return my "Add new object" cell when the indexPath.row = (N + 1), not N = 0? I may be misunderstanding what "N" equates to, but I thought it just meant count of fetched objects.
Yes it is the count of actual objects.
You do want your -tableView:cellForRowAtIndexPath:
to return a cell for your "Add new object" otherwise what is the point? You just want it to return a different type of cell.
All you are doing in this solution is adding a cell that is not part of the NSFetchedResultsController
and then compensating for it when you are retrieving an actual object from the NSFetchedResultsController
and when the user selects a cell.
Upvotes: 2