代码之家  ›  专栏  ›  技术社区  ›  kubi

在UITableView中移动行时崩溃

  •  1
  • kubi  · 技术社区  · 15 年前

    例外情况如下:

    Serious application error.  Exception was caught during 
    Core Data change processing: *** -[NSCFArray removeObjectAtIndex:]: 
    index (0) beyond bounds (0) with userInfo (null)
    

    相关代码如下:

    - (void)tableView:(UITableView *)tableView moveRowAtIndexPath:(NSIndexPath *)fromIndexPath toIndexPath:(NSIndexPath *)toIndexPath 
    {
        NSMutableArray *array = [[fetchedResultsController fetchedObjects] mutableCopy];
    
        id objectToMove = [[array objectAtIndex:fromIndexPath.row] retain];
        [array removeObjectAtIndex:fromIndexPath.row];
        [array insertObject:objectToMove atIndex:toIndexPath.row];
        [objectToMove release];
    
        for (int i=0; i<[array count]; i++) {
            [(NSManagedObject *)[array objectAtIndex:i] setValue:[NSNumber numberWithInt:i] forKey:JKChecklistRow];
        }
        [array release];
    }
    
    - (void)controllerWillChangeContent:(NSFetchedResultsController *)controller 
    {
        [self.tableView beginUpdates];
    }
    
    - (void)controller:(NSFetchedResultsController *)controller 
       didChangeObject:(id)anObject 
           atIndexPath:(NSIndexPath *)indexPath 
         forChangeType:(NSFetchedResultsChangeType)type 
          newIndexPath:(NSIndexPath *)newIndexPath 
    {
        UITableView *tableView = self.tableView;
    
        switch(type) {
            case NSFetchedResultsChangeMove:
                [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationFade];
                // Reloading the section inserts a new row and ensures that titles are updated appropriately.
                [tableView reloadSections:[NSIndexSet indexSetWithIndex:newIndexPath.section] withRowAnimation:UITableViewRowAnimationFade];
                break;
        }
    }
    
    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
        [self.tableView endUpdates];
    }
    

    我怀疑崩溃与核心数据存储与未保存的上下文不同步有关。如果我将上下文保存在 -tableView:moveRowAtIndexPath:fromIndexPath:toIndexPath: 方法,程序崩溃得更快,但我还没弄清楚原因。

    2 回复  |  直到 15 年前
        1
  •  1
  •   Gerd    15 年前

    如果在移动行时使用节,则nsfetchedresultsController和表视图将立即退出同步。我想这是班上的一个错误。所以这不是我经验中未保存的上下文。

    其中一个问题是,移动后索引路径不是最新的,因此该路径上的行数不再正确,这导致“索引越界”。假设您有一个到(1,1)的索引,并删除(1,1)处的行。索引指向(1,1),但第1节的内容不再相同等。

    只需让它对你可见 nsInteger tableSectionCount=[self.tableView numberofSections]; nsuinteger frcSectionCount=[[controller sections]count]; nslog(@“TableSectionCount:%d”,TableSectionCount); nslog(@“frcSectionCount:%d”,frcSectionCount); 你会看到的。

    此外,很难找到国家自然科学基金委使用nsfetchedresultshangemove或nsfetchedresultshangeupdate的所有案例。这很大程度上取决于是否需要对行重新排序。 最后,您必须为每一个特定的情况自己同步tabel视图和nsfrc。最后我花了三天才弄清楚。

    非常有用的是: http://iphonedevelopment.blogspot.com/2009/11/one-fix-to-nsfetchedresultscontroller.html . 我已经给作者发了更多的发现,所以我想会有更新。

    但同样重要的是:关键是保持分区的最新状态。

    祝你好运! 胃食管反流病

        2
  •  1
  •   kubi    15 年前

    我知道了。事实上, Jeff LaMarche 算了出来。

    这段代码救了我:

    - (void)controllerDidChangeContent:(NSFetchedResultsController *)controller {
        // In the simplest, most efficient, case, reload the table view.
        if (!self.tableView.editing) 
            [self.tableView reloadData];
    }
    

    因为我在表视图中移动这些行,所以视图已经反映了这些更改。当我更新数据源时,我的代理将尝试重新排列已移动的行,从而导致崩溃。