UITableView行移动奇怪

时间:2012-06-15 10:53:53

标签: ios uitableview

我有一个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");
}

3 个答案:

答案 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的这个标志,但不是这些......