Reputation: 83
There is something within table sections and sortDescriptors that is driving me crazy. Any help will be much appreciated ;)
What I'm looking for is just displaying an "add" row at the bottom of each self.fetchedResultsController.fetchedObjects section. I'm using a sectionNameKeyPath to show sections in my table view. Up to here everything works perfectly. I've implemented this technique in other parts of my app and works pretty well.
However, the problem comes up when there is no data returned by the FRC and core data doesn't return any entity. If I try to add my first managed object, then app breaks with the following error:
The number of sections contained in the table view after the update (1) must be equal to the number of sections contained in the table view before the update (1), plus or minus the number of sections inserted or deleted (1 inserted, 0 deleted). with userInfo (null)
This is my code so far:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
if ([self.fetchedResultsController.fetchedObjects count] == 0) {
return 1;
}
return [[self.fetchedResultsController sections] count];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
// Return the number of rows in the section.
if ([self.fetchedResultsController.fetchedObjects count] == 0) {
return 1;
}
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:section];
return [sectionInfo numberOfObjects] + 1;
}
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
if ([self.fetchedResultsController.fetchedObjects count] == 0 ) {
static NSString *identificadorCelda2 = @"CeldaNuevoGasto";
UITableViewCell *celda = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identificadorCelda2];
if (celda == nil) {
celda = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identificadorCelda2];
}
return celda;
}
id <NSFetchedResultsSectionInfo> sectionInfo = [[self.fetchedResultsController sections] objectAtIndex:indexPath.section];
NSInteger nsection = [sectionInfo numberOfObjects];
if (indexPath.row == nsection) {
static NSString *identificadorCelda2 = @"CeldaNuevoGasto";
UITableViewCell *celda = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identificadorCelda2];
if (celda == nil) {
celda = (UITableViewCell *)[tableView dequeueReusableCellWithIdentifier:identificadorCelda2];
}
return celda;
}
static NSString *CellIdentifier = @"CeldaGasto";
CeldaGastos *cell = (CeldaGastos *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = (CeldaGastos *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
} .....
For sure I'm doing something wrong, but I can not figure it iut. Do I need to modify NSFetchedResultsController delegate methods as well to respond to additions? Or is it something easiser. Thanks ;)
Update
- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type
{
NSInteger nsection = [self.fetchedResultsController.sections count];
switch(type) {
case NSFetchedResultsChangeInsert:
if (nsection == 1 && [sectionInfo numberOfObjects] == 1) {
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
}
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationFade];
if (!nsection)
[self.tableView insertSections:[NSIndexSet indexSetWithIndex:0] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
Upvotes: 0
Views: 489
Reputation: 1252
If I understand your situation correctly, then you indeed will have to change the NSFetchedResultsController delegate methods as well.
Are you inserting new sections into table view using the -insertSections:withRowAnimation:
method of your table view from some of the NSFetchedResultsController's delegate callbacks?
I do not know exactly what your NSFetchedResultsControllerDelegate's implementation is, but for example consider this situation step by step:
Initially you have no entities fetched, and your -numberOfSectionsInTableView:
method returns 1 for your 'add' row.
After you've inserted an entity and the NSFetchedResultsController's delegate receives its -controller:didChangeSection:atIndex:forChangeType:
callback, where you insert a new section into table view using -insertSections:withRowAnimation:
The table view asks its dataSource by calling the -numberOfSectionsInTableView:
method expecting it to rerurn a value increased by 1 (since you are inserting 1 new section). But the method does still return 1 because the 'add' row is not taken into account anymore.
That will result exactly in the error which you are having.
I guess calling -deleteSections:withRowAnimation:
to remove the 'add' row when it is not needed anymore will solve your problem.
Upvotes: 1