【问题标题】:UITableView animating deletion of all rowsUITableView 动画删除所有行
【发布时间】:2017-01-10 04:06:14
【问题描述】:

当动画删除所有行并因此删除包含UITableView 的所有行的所有部分时,我遇到了这个错误:

CRASH: attempt to delete row 2 from section 0, but there are only 0 sections before the update

特别是,我有一个作为表视图数据源和委托的单例管理器类。我发布了一个NSNotification 告诉表视图删除应该删除的行,并且NSNotification 触发以下方法:

 dispatch_async(dispatch_get_main_queue(), ^{
            if ([[[Manager sharedManager] justDeletedIndices] count] > 0) {
                [mainTableView beginUpdates];
                NSMutableArray <NSIndexPath *> *pathsToDelete = [[Manager sharedManager] justDeletedIndices];
                [mainTableView deleteRowsAtIndexPaths:pathsToDelete withRowAnimation:UITableViewRowAnimationFade];
                [[Manager sharedManager] setJustDeletedIndices:[NSMutableArray new]];
                [mainTableView endUpdates];
            } else {
                [mainTableView reloadData];
            }
        });

该方法的代码依次由Manager 中的方法触发,如下所示:

- (void) deleteMessagesForNotificationObjects: (NSArray <Object *> *) objects {

    // this is where the property that includes the NSIndexPath
    [self p_updatePathsToDeleteForDeletedObjects:objects];

    // this is the notification that should trigger the code above
    [[NSNotificationCenter defaultCenter] postNotificationName:@"RefreshTableView" object:self];

    // this is where I modify the underlying data structures that power
    // the table view's data source
    NSMutableArray *localObjects = [objects mutableCopy];

    for (Object *obj in localObjects) {
        [self deleteMessageWithToken:obj.token andUniqueID:nil andFireDate:obj.displayDate];
    }

    NSArray *allKeys = [self.displayDict allKeys];
    NSMutableArray <NSString *> *keysToDelete = [NSMutableArray new];
    for (NSString *key in allKeys) {
        NSMutableArray <Object *> *currentArr = self.displayDict[key];

        NSMutableArray <Object *> *objsToDelete = [NSMutableArray new];
        for (int i = 0; i < [localObjects count]; i ++) {
            if ([currentArr containsObject:localObjects[i]]) {
                [objsToDelete addObject:localObjects[i]];
            }
        }
        [currentArr removeObjectsInArray:objsToDelete];
        [localObjects removeObjectsInArray:objsToDelete];
        if ([currentArr count] < 1) {
            [keysToDelete addObject:key];
        }
    }

    [self.displayDict removeObjectsForKeys:keysToDelete];
    self.keyOrder = [[[self class] orderedKeysFromDict:self.displayDict] mutableCopy];

}

我不清楚必须以什么顺序发生什么。指示表视图必须以动画方式删除某些行的命令(在此讨论:Add/Delete UITableViewCell with animation?与实际修改基础数据源的顺序有何关系?我按照什么顺序 (1) 为行删除和部分删除设置动画,以及 (2) 实际删除这些行和部分?

【问题讨论】:

  • 先修改数据源,然后告诉表视图。

标签: ios objective-c uitableview


【解决方案1】:

答案是必须在beginUpdatesendUpdates 内修改数据源,而不是在其他方法或代码的其他地方修改。

【讨论】:

  • 这是不正确的。您可以在开始和结束更新之间修改数据源,但这不是必需的。唯一需要的是在调用任何表视图更新方法(如插入、删除等)之前修改数据源。例如,请参阅此苹果文档中的清单 7-8...developer.apple.com/library/content/documentation/…
  • 您的问题中有证据表明您正在做主要工作。也许你真正的问题是你没有按照你想象的顺序执行事情。