ios - 编辑包含 NSFetchedResults 的 TableView

标签 ios objective-c uitableview nsfetchedresultscontroller

当从我的核心数据中删除一个使用 NSFetchedResultsController 获取并显示在 TableView 中的对象时,它不会更新表格。它很好地删除了对象,但是该行仍然保留在那里,直到我交换 View 并返回。我注意到这个问题从 iOS8 才开始出现,但可能是错误的。下面是我的代码:

#pragma mark - Fetched Results Controller Delegate

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath {

    return YES;
}

// Override to support editing the table view.
- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {

    if (editingStyle == UITableViewCellEditingStyleDelete) {

        NSManagedObjectContext * context = [self managedObjectContext];
        entity * rowToDelete = [self.fetchedResultsController objectAtIndexPath:indexPath];

        [context deleteObject:rowToDelete];

        //check that the row has deleted data
        NSLog(@"Shhiiiiiiiiii...... You done did delete a row...");

        NSError * error = nil;
        if (![context save:&error]){
            NSLog(@"Error: %@", error);
        }

        //causes a crash
        //[self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];

        //DOES NOT UPDATE THE TABLE        
        [self.tableView reloadData];
    }

}

我像这样使用所有正常的代表:

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

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

- (void) controller:(NSFetchedResultsController *)controller didChangeObject:(id)anObject atIndexPath:(NSIndexPath *)indexPath forChangeType:(NSFetchedResultsChangeType)type newIndexPath:(NSIndexPath *)newIndexPath{

switch (type) {
    case NSFetchedResultsChangeInsert:
        [self.tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath] withRowAnimation:UITableViewRowAnimationRight];
        break;
    case NSFetchedResultsChangeDelete:
        [self.tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
        break;

    case NSFetchedResultsChangeUpdate:{
        entity * details = [self.fetchedResultsController objectAtIndexPath:indexPath];
        UITableViewCell *cell = [self.tableView cellForRowAtIndexPath:indexPath];
        cell.textLabel.text = details.detailString;
    }
        break;

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

    }

}

-(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:UITableViewRowAnimationRight];
        break;

    case NSFetchedResultsChangeDelete:
        [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex] withRowAnimation:UITableViewRowAnimationRight];
        break;

    case NSFetchedResultsChangeMove:
        NSLog(@"A table item was moved");
        break;
    case NSFetchedResultsChangeUpdate:
        NSLog(@"A table item was updated");
        break;

    }

}

我在 Stack 上搜索并找到了通用响应“您需要使用 [self.tableView deleteRowsAtIndexPaths:@[indexPath] withRowAnimation:UITableViewRowAnimationRight];”。这是行不通的。

在此先感谢您的帮助。如果我没有立即回复,那是因为我正在休息或睡着了;-)

最佳答案

NSFetchedResultsController 应该能够为您传达所有更改。

  • 检查是否正在调用更新函数(即缩小可能失败的范围)
  • 检查 NSFetchedResultsController 实例是否设置了委托(delegate)
  • 检查您是否在相同或连接的上下文中工作(即检查通知是否有传播的机会)
  • 我不确定您是否可以忽略重新排序(可能取决于您的方法)但想象一下 [对象 A,第 1 行] 与 [对象 B,第 2 行] 交换,然后对象 B 被删除,如何系统是否知道要删除哪个表行(除非你对信息做一些额外的事情)

从表中手动删除一行将导致崩溃,因为数据源将与表不一致——因此,会导致各种困惑。结果的委托(delegate)方法可以使实际结果与表中显示的结果同步。

我从一个工作演示中删除了以下内容(尽管在途中修改了一堆东西)。它工作并接收更改,并更新表。仅通过 google 搜索一些博客文章也能提供帮助。

- (void)viewDidLoad {
    [super viewDidLoad];
    _fetchedResultsController = /* my fetched results controller... */;
    _fetchedResultsController.delegate = self;
}

#pragma mark - Table view data source

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    NSInteger count = [[_fetchedResultsController sections] count];
    return count;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    id sectionInfo = [[_fetchedResultsController sections] objectAtIndex:section];
    NSInteger count = [sectionInfo numberOfObjects];
    return count;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
    return [self configureCell:nil atIndexPath:indexPath];
}


- (UITableViewCell *)configureCell:(UITableViewCell*)cell atIndexPath:(NSIndexPath*)indexPath {
    id obj = [self.fetchedResultsController objectAtIndexPath:indexPath];
    if(!cell) {
        cell = [self.tableView dequeueReusableCellWithIdentifier:@"MyTableViewCell" forIndexPath:indexPath];
    }
    cell.textLabel.text = obj.someProperty;
    return cell;
}

#pragma mark NSFetechResults delegate

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

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

    switch(type) {
        case NSFetchedResultsChangeInsert:
            [self.tableView insertSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                          withRowAnimation:UITableViewRowAnimationAutomatic];
            break;

        case NSFetchedResultsChangeDelete:
            [self.tableView deleteSections:[NSIndexSet indexSetWithIndex:sectionIndex]
                          withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
        default:
            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:UITableViewRowAnimationAutomatic];
            break;

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

        case NSFetchedResultsChangeUpdate:
            [self configureCell:[tableView cellForRowAtIndexPath:indexPath]
                    atIndexPath:indexPath];
            break;
        case NSFetchedResultsChangeMove:
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationAutomatic];
            [tableView insertRowsAtIndexPaths:[NSArray arrayWithObject:newIndexPath]
                             withRowAnimation:UITableViewRowAnimationAutomatic];
            break;
    }
}

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

关于ios - 编辑包含 NSFetchedResults 的 TableView,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/28898979/

相关文章:

ios - 设计循环 "selector"控件

ios - block 中的 WeakSelf

ios - 动态添加部分到 UITableView,然后动态添加子单元格到特定部分。

ios - 解除多个 View Controller 的委托(delegate)问题

ios - Swift - 将 UIRefreshControl 添加到表的节标题 View

objective-c - iOS SQLite 性能低下

objective-c - Swift 中的 NSOpenPanel 。如何打开?

iOS TableView : Grouping rows into sections

ios - Dealloc 方法从 XCode 4.1 UIViewController 模板中消失

ios - iOS 中使用 Twitter API 的简单 GET 请求