仍然在努力解决这个问题。我正在读取coredata中的数据,并使用NSFetchedResultsController将其呈现在表视图中。问题是,我希望我的用户能够一次编辑所有内容:重新排序,重命名行中的文本字段,删除行并添加新行。
到目前为止,我(几乎!)在用户驱动的更改发生后立即使用转义所有NSFetchedResultsController委托方法顺利工作: 即:
- (void)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
if (self.suspendAutomaticTrackingOfChangesInManagedObjectContext) return;
只要在我的表视图中启动编辑模式,我就将此属性设置为YES。重新排序后,我重新获取整个获取请求并重新加载表。我只停止挂起并在添加或删除项目时将此属性设置为NO:
- (void)tableView:(UITableView *)aTableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle
forRowAtIndexPath:(NSIndexPath *)indexPath
{
// Update the data model according to edit actions delete or insert.
if (editingStyle == UITableViewCellEditingStyleDelete) {
//Basically saves the textfield
if (self.activeField && [self.activeField isFirstResponder]){
[self.activeField resignFirstResponder];
}
self.suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;
[self.managedObjectContext deleteObject:[self.fetchedResultsController objectAtIndexPath:indexPath]];
//Results in a strange delete button behaviour. If omitted the order should still be valid.
// //Adjust the indices of the remaining entries
// int i = 1;
// for (MainCategory *fetchedResult in [self.fetchedResultsController fetchedObjects])
// {
// fetchedResult.position = [NSNumber numberWithInt:i++];
// }
}
}
在我的文本字段中我做了结束编辑方法:
-(void)textFieldDidEndEditing:(UITextField *)textField
{
NSIndexPath *indexPath = [NSIndexPath indexPathForRow:textField.tag inSection:0];
MainCategory *mainCategory = [self.fetchedResultsController objectAtIndexPath:indexPath];
if(textField.text != mainCategory.name){
mainCategory.name = textField.text;
}
self.activeField = nil;
}
现在你可以看到我目前唯一的问题了:如果我在说第3行的文本字段,我将删除第2行,有时(并非总是!)删除之前的行号4现在排第3行,获取我之前编辑的文本字段的文本。我想这是因为我使用IndexPath设置了主类别名称。可能NSFetchedResultsController在那里搞砸了......
知道为什么或我能做什么?我想完全避免使用NSFetchedResultsController委托并且只是一直在重新发送一些更改。但这应该和我现在的结果基本相同而且不是真的更快......所以我应该怎么做?
编辑: FRC委托方法
#pragma mark - NSFetchedResultsControllerDelegate
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if (self.suspendAutomaticTrackingOfChangesInManagedObjectContext) return;
[self.tableView beginUpdates];
}
- (void)controller:(NSFetchedResultsController *)controller
didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
atIndex:(NSUInteger)sectionIndex
forChangeType:(NSFetchedResultsChangeType)type
{
if (self.suspendAutomaticTrackingOfChangesInManagedObjectContext) return;
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)controller:(NSFetchedResultsController *)controller
didChangeObject:(id)anObject
atIndexPath:(NSIndexPath *)indexPath
forChangeType:(NSFetchedResultsChangeType)type
newIndexPath:(NSIndexPath *)newIndexPath
{
if (self.suspendAutomaticTrackingOfChangesInManagedObjectContext) return;
switch(type) {
case NSFetchedResultsChangeInsert:
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeDelete:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeUpdate:
[self.tableView reloadRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
case NSFetchedResultsChangeMove:
[self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
[self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationFade];
break;
}
}
- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller
{
if(self.suspendAutomaticTrackingOfChangesInManagedObjectContext) return;
[self.tableView endUpdates];
}
- (void)endSuspensionOfUpdatesDueToContextChanges
{
_suspendAutomaticTrackingOfChangesInManagedObjectContext = NO;
}
- (void)setSuspendAutomaticTrackingOfChangesInManagedObjectContext:(BOOL)suspend
{
if (suspend) {
_suspendAutomaticTrackingOfChangesInManagedObjectContext = YES;
} else {
[self performSelector:@selector(endSuspensionOfUpdatesDueToContextChanges) withObject:0 afterDelay:0];
}
}
答案 0 :(得分:0)
FRC仍然在滚动时为您提供批量加载,因此即使您滥用委托功能,仍然值得保留它。
您的问题实际上是在编辑完成时使用标记。实际上你应该在编辑开始时记录行索引。如果您在编辑后没有更新整个表格,则需要小心使用字段标记,因为您可能有多个重复的标记和错误的标记。
解决方案是自定义单元格,其中单元格是字段的委托。编辑时,该字段通知单元格,单元格通知控制器。然后,您可以从表格视图中实际从单元格和索引中获取信息。