【问题标题】:UITableView crashes when trying to delete a cell and section尝试删除单元格和部分时 UITableView 崩溃
【发布时间】:2012-04-22 16:21:19
【问题描述】:

我一直致力于创建一个 UITableView,它的内容从 NSUserDefaults 对象加载。但是,每当我尝试删除单元格/部分时,程序就会崩溃并吐出以下内容:

*** Assertion failure in -[UITableView _endCellAnimationsWithContext:], /SourceCache/UIKit_Sim/UIKit-1912.3/UITableView.m:1030
*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Invalid update: invalid number of sections.  The number of sections contained in the table view after the update (2) must be equal to the number of sections contained in the table view before the update (3), plus or minus the number of sections inserted or deleted (0 inserted, 0 deleted).

无论我阅读了多少关于此错误并尝试修复它,过去几个小时我都被困在这里。这是我在用户点击“删除”按钮时调用的方法:

 (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        //[[[NSUserDefaults standardUserDefaults] objectForKey:@"rawArray"] removeObjectAtIndex:indexPath.row];
        //[[[NSUserDefaults standardUserDefaults] objectForKey:@"rawDates"] removeObjectAtIndex:indexPath.row];

        NSMutableArray *rawArray = [[NSUserDefaults standardUserDefaults] objectForKey:@"rawArray"];
        NSMutableArray *rawDates = [[NSUserDefaults standardUserDefaults] objectForKey:@"rawDates"];

        [rawArray removeObjectAtIndex:indexPath.row];
        [rawDates removeObjectAtIndex:indexPath.row];

        [[NSUserDefaults standardUserDefaults] setObject:rawArray forKey:@"rawArray"];
        [[NSUserDefaults standardUserDefaults] setObject:rawDates forKey:@"rawDates"];

        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
        [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];

    }    
}

以下是用于确定行数和单元格数的方法:

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView{
    return [[[NSUserDefaults standardUserDefaults] arrayForKey:@"rawDates"] count];
}

- (NSString *)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{

    return [[[NSUserDefaults standardUserDefaults] arrayForKey:@"rawDates"] objectAtIndex:section];
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{
    return 1;
}

那里的最后一个方法返回一个,因为到目前为止,我计划每个部分只有一个单元格。感谢您抽出宝贵的时间来看这里,我真的希望您能帮助我! :/

【问题讨论】:

  • 我猜你忘了打电话给[tableView beginUpdates];[tableView endUpdates];
  • 你是否相应地更新了数据源模型;

标签: iphone xcode uitableview crash


【解决方案1】:

查看Batch Insertion, Deletion, and Reloading of Rows and Sections

基本上你需要调用这些方法

- (void)insertSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)deleteSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;
- (void)reloadSections:(NSIndexSet *)sections withRowAnimation:(UITableViewRowAnimation)animation;

- (void)insertRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)deleteRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation: (UITableViewRowAnimation)animation;
- (void)reloadRowsAtIndexPaths:(NSArray *)indexPaths withRowAnimation:(UITableViewRowAnimation)animation;

之间

- (void)beginUpdates;
- (void)endUpdates;

例如

[tableView beginUpdates];
[tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
[tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];
[tableView endUpdates];

您的数据源还需要在调用 endUpdates 时反映更改


就我个人而言,我喜欢创建一个类别来围绕它提供一个基于块的包装器

  1. 别忘了给endUpdates打电话
  2. 它允许缩进看起来正确/自动

UITableView上的类别

@interface UITableView (PSAdditions)

- (void)ps_updates:(void (^)(void))updateBlock;

@end

@implementation UITableView (PSAdditions)

- (void)ps_updates:(void (^)(void))updateBlock;
{
    [self beginUpdates];
    if (updateBlock) { updateBlock(); }
    [self endUpdates];
}

看起来像这样

[tableView ps_updates:^{
    [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath] withRowAnimation:UITableViewRowAnimationRight];
    [tableView deleteSections:[NSIndexSet indexSetWithIndex:indexPath.section] withRowAnimation:UITableViewRowAnimationRight];
}];

【讨论】:

  • 哦,哇,这立即奏效了。我不敢相信这有多么简单——我真的应该在深入研究之前阅读所有开发人员文档。我肯定也会考虑制作 UITableView (PSAdditions) 子类,感谢您的建议。非常感谢你,你不知道你让我开心了多少。 :)
  • 使用 beginUpdates 和 endUpdates 一直运行良好,但只是我第一次删除某些内容。第二次,我总是收到一条消息:*** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '-[__NSCFArray removeObjectAtIndex:]: mutating method sent to immutable object'。我四处搜寻,发现问题很可能与我的 numberOfRowsInSection 方法有关,但我不确定如何更改它,因为我每个部分只需要 1 个单元格,而且我不跟踪我删除的内容(我不知道我会怎么做)。 ://
  • 快速澄清这不是我展示的子类,它是一个“类别”,如果你给它一个快速的谷歌,你会发现大量的例子等你的第二条评论 - 你需要确保tableView 的数据源反映了对 tableView 所做的任何更改。如果您需要帮助,最好用一些更具体的细节开始一个新问题
  • 好的,再次感谢您提供的更新和信息,您帮了大忙。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2018-02-06
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多