我有一个UITableView,配置为允许在编辑模式下在各部分之间移动行。该表使用NSFetchedResultsController
进行备份很难描述我所看到的问题,但实质上是:
1)用户开始拖动行
2)当其他行被拖到桌子周围时,其他行会移出它
3)用户释放触摸,我响应moveRowAtIndexPath:回调(代码 通过适当更新ManagedObject
4)现在,由于某些原因,其他行动画回到用户开始拖动之前的位置。也就是说,所有人都向上或向下移动到他们之前的位置,而不是保持新的位置。
一段时间后,通常在0.5秒到3秒之间,NSFetchResultsController决定让我更新移动的单元格。此时我最终调用[table beginUpdates]和[table endUpdates]并将行移动到应该执行的位置。
现在,来自NSFetchResultsController的延迟回调是一个奇怪的但是这似乎很重要。重要的是UITableView不会将行保留在新位置,并且需要将开始/结束更新调用放在它们应该位于的位置。我应该在此回调中做些其他事情:
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath
{
NSLog(@"UI is moving row from [%d, %d] to [%d, %d]", fromIndexPath.section, fromIndexPath.row, toIndexPath.section, toIndexPath.row);
self.inManualReorder = YES;
// Here I update the underlying object, code is not relevant as this works.
...
// I've tried saving the context here and delaying it untill later on. It doesn't affect
// the behavior in question.
NSError *error = nil;
if (![self.managedObjectContext save:&error]) {
// Replace this implementation with code to handle the error appropriately.
// abort() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
NSLog(@"Unresolved error %@, %@", error, [error userInfo]);
abort();
}
self.inManualReorder = NO;
NSLog(@"UI finished moving row");
}
答案 0 :(得分:1)
之前我遇到过同样的问题。 来自Stanford CS193p的CoreDataTableViewController正常使用suspendAutomaticTrackingOfChangesInManagedObjectContext属性。它在手动更新期间忽略来自托管对象上下文的更新。
- (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)destinationIndexPath
{
NSError *error = nil;
[self setSuspendAutomaticTrackingOfChangesInManagedObjectContext:YES];
// yourown code here ...
[self setSuspendAutomaticTrackingOfChangesInManagedObjectContext:NO];
[self performFetch];
}
答案 1 :(得分:0)
你如何保持取得的结果?在一个数组?
似乎表格在此阵列更新之前正在重新加载,然后再次更新(之后不久)
尝试实施
- (void)tableView:(UITableView*)tableView didEndEditingRowAtIndexPath:(NSIndexPath *)indexPath;
按照您当前的操作更新托管对象,但将其保存在此方法中,然后获取结果并设置阵列。最后,在UITableView上调用reloadData(其代理人(即您的视图控制器)访问该结果数组。
编辑: 你是否在更新区内进行表更新,即
[tableView beginUpdates];
// ...Move cell...
[tableView endUpdates];
答案 2 :(得分:0)
我找到了。
在回调到控制器的时候(已)改变了我正在调用的开始(结束)更新。如果重新排序来自人工干预,我不应该这样做:
- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller
{
if (!self.inManualReorder)
[self.tableView beginUpdates];
}
我正在检查didChangeObject:callback的这个标志,但不是这些......