由于NSManagedObjectContext保存更新NSFetchedResultsController时延迟UITableView更新

时间:2010-07-15 01:34:58

标签: iphone design-patterns core-data nsfetchedresultscontroller

我正在使用NSFetchedResultsController的谓词对UITableView进行排序。但是,当我在详细视图中进行更改并保存它时,我立即更改的对象将被放置在UITableView中的新位置。

我有向上/向下按钮,类似于Mail中的消息视图。此行为会中断项目的排序,我希望延迟此更改,直到用户退出UITableView for UX。我在UITableViewController中实现了NSFetchedResultsControllerDelegate方法。有这么简单/聪明的方法吗?

编辑:下面是在UITableViewController中实现的NSFetchedResultsControllerDelegate方法。

- (void)controllerWillChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView beginUpdates];
}


- (void)controller:(NSFetchedResultsController *)controller didChangeSection:(id <NSFetchedResultsSectionInfo>)sectionInfo
           atIndex:(NSUInteger)sectionIndex forChangeType:(NSFetchedResultsChangeType)type {

    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 {

    UITableView *tableView = self.tableView;

    switch(type) {

        case NSFetchedResultsChangeInsert:
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeDelete:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath]
                    atIndexPath:indexPath];
            break;

        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationFade];
            break;
    }
}


- (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
    [self.tableView endUpdates];
}

2 个答案:

答案 0 :(得分:3)

问题不在NSFetchedResultsControllerDelegate方法中。这些方法仅在表格可见时更改数据模型时才起作用。

您的问题是在表格视图处于关闭状态且处于非活动状态时更改数据。 Tableviews旨在自动显示给定的数据模型。当您从详细信息视图返回到tableview时,它会自动重新加载其数据,该数据现在包含在详细信息视图中所做的更改。无论您如何向表格提供数据,它都会这样做。

在您希望更改显示之前,阻止表显示更改的唯一方法是不将数据添加到数据模型。您必须将数据从详细信息视图传递回非托管对象中的表,并在您希望它出现时在tableview控制器中创建managedObject。

但是,从UI设计的角度来看,我建议您重新考虑您的设计。如果您在重新加载之前不更改表格,您将如何向用户表明您将进行更改?用户界面是否会突然更新而没有明显的原因?用户是否必须启动它?如果他们忘了怎么办?

我认为用户会期望在详细视图中进行的任何更改都会立即反映在tableview中,因为这几乎是所有tableview-detailView配对的工作方式。例如,如果您更改地址簿的联系人详细信息中的联系人姓名,则在您返回联系人列表时会立即反映该名称。

答案 1 :(得分:0)

我使用的一个技巧是在您呈现详细视图控制器时调用beginUpdates,然后在完成消失时endUpdates。 E.g。

-(void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender{
    if([segue.identifier isEqualToString:@"showDetail"]){

        // configure detail controller

        // makes row appear after modal disappears.
        [self.tableView beginUpdates];
        [v setViewDidDissapear:^(BOOL animated) { // custom block added 
            [self.tableView endUpdates];
        }];
    }
}