ios – insertRowsAtIndexPaths:with scrollToRowAtIndexPath:导致UITableView部分被错误地隐藏

我创建了一个UITableview,其中包含可点击的部分.当你点击它们时

>他们“扩大”以揭示其中的细胞
>单击的部分滚动到视图的顶部.

我计算所有索引路径以插入/删除必要的单元格,然后使用以下代码插入它们:

[self.tableView beginUpdates];
[self.tableView insertRowsAtIndexPaths:pathsToOpen withRowAnimation:insertAnimation];
[self.tableView deleteRowsAtIndexPaths:pathsToClose withRowAnimation:deleteAnimation];
[self.tableView endUpdates];
[self.tableView scrollToRowAtIndexPath:[pathsToOpen objectAtIndex:0]  atScrollPosition:UITableViewScrollPositionTop animated:YES];

只有一个问题 – 所选部分下面的部分是隐藏的.第一个屏幕截图显示了tableview的外观.第二个屏幕截图显示了它的实际外观.

如果向上滚动(所以隐藏的部分在屏幕外),然后向下滚动,隐藏的部分将被带回(再次可见).我猜测为什么会发生这种情况如下:

插入/删除动画与scrollToRowAtIndexPath同时发生,并且它使TableView混乱.如果我还没有完成scrollToRowAtIndexPath第3节& 4会出现在屏幕外 – 因此tableView仍然认为它们在屏幕外. UITableview将屏幕外的单元格/部分隐藏为优化.如果我用dispatch_after用2秒调用scrollToRowAtIndexPath,那么第3节& 4正确显示.

所以我想我知道为什么会这样,但我不知道如何修复/覆盖这个UITableview优化.实际上,如果我实现scrollViewDidEndScrollingAnimation,然后在此函数中添加断点,则应用程序将显示第3和第3部分. 4正确(这就是我第一次拍摄屏幕的方式).但是一旦继续这个功能,细胞就会消失.

完整的项目可以下载here

其他实现细节:Sections是合法的UITableView部分.我添加了一个tapGestureRecognizer,用于触发对tableview的委托回调.下面包含打开这些部分的整个方法.

- (void)sectionHeaderView:(SectionHeaderView *)sectionHeaderView sectionOpened:(NSInteger)sectionOpened
{
    // Open
    sectionHeaderView.numRows = DefaultNumRows;
    sectionHeaderView.selected = YES;
    NSMutableArray *pathsToOpen = [[NSMutableArray alloc] init];
    for (int i = 0; i < sectionHeaderView.numRows; i++)
    {
        NSIndexPath *pathToOpen = [NSIndexPath indexPathForRow:i inSection:sectionOpened];
        [pathsToOpen addObject:pathToOpen];
    }

    // Close
    NSMutableArray *pathsToClose = [[NSMutableArray alloc] init];
    if (openSectionHeader)
    {
        for (int i = 0; i < openSectionHeader.numRows; i++)
        {
            NSIndexPath *pathToClose = [NSIndexPath indexPathForRow:i inSection:openSectionHeader.section];
            [pathsToClose addObject:pathToClose];
        }
    }

    // Set Correct Animation if section's already open
    UITableViewRowAnimation insertAnimation = UITableViewRowAnimationBottom;
    UITableViewRowAnimation deleteAnimation = UITableViewRowAnimationTop;
    if (!openSectionHeader || sectionOpened < openSectionHeader.section)
    {
        insertAnimation = UITableViewRowAnimationTop;
        deleteAnimation = UITableViewRowAnimationBottom;
    }

    openSectionHeader.numRows = 0;
    openSectionHeader.selected = NO;
    openSectionHeader = sectionHeaderView;


    [self.tableView beginUpdates];
    [self.tableView insertRowsAtIndexPaths:pathsToOpen withRowAnimation:insertAnimation];
    [self.tableView deleteRowsAtIndexPaths:pathsToClose withRowAnimation:deleteAnimation];
    [self.tableView endUpdates];
    [self.tableView scrollToRowAtIndexPath:[pathsToOpen objectAtIndex:0]  atScrollPosition:UITableViewScrollPositionTop animated:YES];
}
最佳答案
据我所知,返回已经使用过的剖面视图时会出现问题.代替:

- (UIView *)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section
{
    return [self.sectionHeaderViews objectAtIndex:section];
}

如果我每次创建一个新视图,我都没有问题:

- (UIView *)tableView:(UITableView*)tableView viewForHeaderInSection:(NSInteger)section{
    SectionHeaderView *sectionHeaderView = [self.tableView dequeueReusableCellWithIdentifier:SectionHeaderView_NibName];
    sectionHeaderView.textLabel.text = [NSString stringWithFormat:@"Section %d", section];

    UITapGestureRecognizer *tapRecognizer = [[UITapGestureRecognizer alloc] initWithTarget:sectionHeaderView action:@selector(handleTap:)];
    [sectionHeaderView addGestureRecognizer:tapRecognizer];
    sectionHeaderView.section = section;
    sectionHeaderView.delegate = self;
    return sectionHeaderView;
}

这可能是因为你正在使用[self.tableView dequeueReusableCellWithIdentifier:SectionHeaderView_NibName];创建节标题并在数组中保留它们,我不认为UITableViewCell是为其创建的,但我不确定.您可能需要考虑前面的UITableViewCell用于剖面视图,而是使用其他东西(可能是带有UILabel的UIImageView).或者你不能将剖面视图存储在一个数组中…你目前设置代码的方式,你不需要数组并创建一个新视图是微不足道的,你不需要担心它.

转载注明原文:ios – insertRowsAtIndexPaths:with scrollToRowAtIndexPath:导致UITableView部分被错误地隐藏 - 代码日志