I have UITableViewController
subclassed and implemented the following
NSFetchedResultsController
with its delegatestableView:sectionForSectionIndexTitle:atIndex:
tableView:titleForHeaderInSection:
In controller:didChangeObject:atIndexPath:forChangeType:newIndexPath:
case NSFetchedResultsChangeMove:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
In data model for the given entity I have transient property uppercaseFirstLetterOfName
which will return first letter of persistent property.
This is all to achieve Alphabetical sections for table items and side index.
Now if I have a single record for a section, then I rename it so it will change the section, I get the following exception, which happens somewhere after NSFetchedResultsChangeMove
.
*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-984.38/UITableView.m:774
Exception was caught during Core Data change processing: Invalid update: invalid number of rows in section 0. The number of rows contained in an existing section after the update (1) must be equal to the number of rows contained in that section bef开发者_开发百科ore the update (1), plus or minus the number of rows inserted or deleted from that section (0 inserted, 1 deleted).
Any ideas?
UPD some more code:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
NSInteger count = [[fetchedResultsController sections] count];
return count;
}
- (NSInteger)tableView:(UITableView *)tableView
numberOfRowsInSection:(NSInteger)section
{
NSInteger numberOfRows = 0;
if ([[fetchedResultsController sections] count] > 0)
{
id <NSFetchedResultsSectionInfo> sectionInfo =
[[fetchedResultsController sections] objectAtIndex:section];
numberOfRows = [sectionInfo numberOfObjects];
}
return numberOfRows;
}
...
NSSortDescriptor* sortByWordDescriptor = [[NSSortDescriptor alloc]
initWithKey:@"subject" ascending:YES];
NSArray* sortArray = [[NSArray alloc]
initWithObjects:sortByWordDescriptor, nil];
[fetchRequest setSortDescriptors:sortArray];
NSFetchedResultsController* controller = [[NSFetchedResultsController alloc]
initWithFetchRequest:fetchRequest
managedObjectContext:managedObjectContext
sectionNameKeyPath:@"uppercaseFirstLetterOfName"
cacheName:@"Root"];
UPD(patched): At the moment I patched the code like this:
case NSFetchedResultsChangeMove:
NSUInteger tableSectionCount = [self.tableView numberOfSections];
NSUInteger modelSectionCount = [[controller sections] count];
if (modelSectionCount > tableSectionCount)
{
[self.tableView insertSections:[NSIndexSet
indexSetWithIndex:[newIndexPath section]]
withRowAnimation:UITableViewRowAnimationNone];
}
else if(modelSectionCount < tableSectionCount)
{
if (tableSectionCount > 1)
{
[self.tableView deleteSections:[NSIndexSet
indexSetWithIndex:[indexPath section]]
withRowAnimation:UITableViewRowAnimationNone];
}
}
[tableView deleteRowsAtIndexPaths:[NSArray
arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray
arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
break;
So far no crash, but is this correct solution?
I think I know what's happening to you. Make sure you have:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
[self.tableView beginUpdates];
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
[self.tableView endUpdates];
}
The documentation says about "beginUpdates" method:
Call this method if you want subsequent insertions, deletion, and selection operations (for example, cellForRowAtIndexPath: and indexPathsForVisibleRows) to be animated simultaneously.
which is what you're doing with:
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
Cheers
The code that handles the sections is going to expect an item to be at a certain index but that item is no longer there and it doesn't seem you have coded for that scenario by returning nil when there's no item there.
you should modify the datasource array before do any insert or delete method of tableView!
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
withRowAnimation:UITableViewRowAnimationFade];
[tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
withRowAnimation:UITableViewRowAnimationFade];
and NSFetchedResultsChangeMove
should finish your UI movement action.
so what you need do is to reorder the datasorce items.
精彩评论