Ios 删除UITableView';后,标题视图的框架将永久更改;s部分

Ios 删除UITableView';后,标题视图的框架将永久更改;s部分,ios,objective-c,uitableview,uiview,Ios,Objective C,Uitableview,Uiview,我正在重用标题,将它们保存在字典中,其中节号是键,标题视图是值 在我设置动画删除一个部分并重新加载另一个部分后,只有这些部分的标题视图“消失”。经过一些搜索,我发现这些标题视图的框架已经更改标题视图的Frame.X,该标题视图从使用UITableViewRowAnimationRight按屏幕宽度向右移动(320)的节中删除,并使用UITableViewRowAnimationAutomatic按Y移动的节重新加载 主要的问题和困惑来自我无法更改这些帧的事实!首先,它们会发生变化,但视觉上没有任

我正在重用标题,将它们保存在字典中,其中节号是键,标题视图是值

在我设置动画删除一个部分并重新加载另一个部分后,只有这些部分的标题视图“消失”。经过一些搜索,我发现这些标题视图的框架已经更改<代码>标题视图的Frame.X,该标题视图从使用
UITableViewRowAnimationRight
按屏幕宽度向右移动(320)的节中删除,并使用
UITableViewRowAnimationAutomatic
Y
移动的节重新加载

主要的问题和困惑来自我无法更改这些帧的事实!首先,它们会发生变化,但视觉上没有任何变化,在另一个调用
viewForHeaderInSection:
的过程中,帧会再次移动

我是这样做的:

假设我们有3个部分,每个部分的数据放在一个数组中,分别是
\u first
\u second
\u third
。通过按钮的触碰,我们称之为
handleTouchUp:
。(
\u秒
保持不变)

更新:
项目中可能还有其他一些错误,但这并不重要——这是测试项目。唯一重要的问题是标题视图无效。删除无效视图并创建新视图并不是解决方案——它扼杀了重复使用标题视图的意义。

我在您的项目中发现了几个错误,这些错误实际上导致了一些崩溃,我相信它们也是您在应用程序中看到的标题视图错误的原因。 在我修复了这些之后,应用程序对我来说似乎运行正常

以下是项目的更新版本:

我试图使它尽可能地与您最初的项目相似,但我不得不做一些更改。如果您认为它与您想要的功能不匹配,请留下评论,我将进行更新(这就是我推断项目应该表现的样子) 下面解释的所有更改也可以在这个更新的项目中看到

我发现的问题与这样一个事实有关:如果从表视图中删除一个节,则该节之后的所有节的索引都将发生更改(使用-1)。这是正常的,因为节索引实际上是一个索引,而不是分配给每个节的唯一键

删除第一节后,第三节现在的索引为1,表视图委托方法读取数据不正确(包括标题视图),因为所有内容都基于节索引

为了解决这个问题,我更改了header视图缓存,将数据数组用作键(_first、_second或_third)。 为了简化此过程,我创建了一个方法,该方法可以从多个位置调用,并根据节索引和当前节计数返回正确的数据数组:

- (NSArray*)dataArrayForSection:(NSInteger)section
{
    if (sectionCount == 3)
    {
        switch (section)
        {
            case 0: return _first;
            case 1: return _second;
            case 2: return _third;
        }
    }
    else
    {
        switch (section)
        {
            case 0: return _second;
            case 1: return _third;
        }
    }

    return nil;
}
既然标头缓存使用数据数组作为键,那么在
handleTouchUp
方法中重新分配数组时,删除标头条目就很重要了

- (void) handleTouchUp: (UIButton *)sender
{
    NSLog(@"Touched!");
    if ([_first count] == 0)
    {
        sectionCount = 3;

        // **INSERTED** Removes the cache for the _first and _third keys because you are recreating the arrays again,
        // and so you are losing the initial key. Not doing this, results in a memory leak
        [_headers removeObjectForKey:_first];
        [_headers removeObjectForKey:_third];

        _first = [NSMutableArray arrayWithObjects: @"First 1", @"First 2", nil];
        _third = [NSMutableArray arrayWithObjects: @"Third 1", @"Third 2", @"Third 3", @"Third 4", @"Third 5", nil];

        [tableView reloadData];
//        [tableView beginUpdates];
//        [tableView reloadSections: [NSIndexSet indexSetWithIndex: 0] withRowAnimation:UITableViewRowAnimationRight];
//        [tableView reloadSections: [NSIndexSet indexSetWithIndex: 2] withRowAnimation:UITableViewRowAnimationAutomatic];
//        [tableView endUpdates];
    }
    else
我改进的另一件事是重用表视图单元格。您应该始终尝试重用现有的UITableViewCells(很少有例外)。
cellforrowatinexpath
现在看起来如下所示:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray* dataarray = [self dataArrayForSection:indexPath.section];


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"my_text_cell"];
    if (cell == nil)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"my_text_cell"];


    if (dataarray == nil)
        cell.textLabel.text = @"default";
    else
        cell.textLabel.text = [dataarray objectAtIndex:indexPath.row];


    return cell;
}
如果您有任何问题,请留下评论

编辑

我试图按照您的要求更新我的测试项目,以保持缓存完好无损,并且我确实能够重现错误-在删除/重新加载动画之后,最后一节的标题不可见

我发现iOS选择的自动重新加载动画是淡入淡出动画。 这会导致标题视图淡出。我通过在应用程序中添加另一个按钮来测试这一点,该按钮为所有缓存的标题视图设置alpha=1。重新加载动画后,我按下此按钮,标题视图正确显示

我尝试使用其他动画,但它们看起来不太好

最后,我不认为苹果建议缓存标题视图。在文档中,从iOS 6.0开始,有一种新方法解决了这个问题。其行为类似于出列单元格,但用于页眉/页脚视图
-(id)带标识符的出列可重用HeaderFooterViewWithIdentifier:(NSString*)标识符

因此,如果您以iOS 6.0+为目标,那么您可以使用它而不是手动缓存标头。否则,我找到的解决方案是只从缓存中删除已删除和重新加载的节的头视图(_first和_third)


我更新了项目,以便在刷新时仅删除最后一个节标题

,重点是标题视图的帧在动画删除/重新加载后变得无效。所有其他错误(包括重复使用单元格)其实并不重要,因为这只是我编写的测试项目,用于显示标题视图框架的问题。您的项目没有此问题的原因是,您总是在重新创建受动画影响的标题视图,而不这样做是标题视图“缓存”的全部要点。我也没有收到你们关于丢失初始关键点的评论(就在从缓存中删除标题之前)。但无论如何,标题视图不应该在动画之后被破坏,这是错误的。如果我想使用外观完全相同的视图,我应该能够使用完全相同的视图,如果它没有损坏,并且该视图在视图层次结构中只显示一次。如果可以的话,请尽量不要清除缓存,最终会导致视图损坏。我将尝试更好地解释错误键的含义。您已经缓存了键0、1、2的标题视图。当您删除第一节(index=0)并刷新第2节时,将使用index=1调用该刷新-因为第一节消失,而所有其他节都用-1移位。因此,在标题刷新中,基于代码,您将返回带有键1的标题视图,但该确切的uiview也用于上一个第二节(未刷新,它保留了旧的标题视图)。在两个位置具有相同的UIView
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    NSArray* dataarray = [self dataArrayForSection:indexPath.section];


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"my_text_cell"];
    if (cell == nil)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"my_text_cell"];


    if (dataarray == nil)
        cell.textLabel.text = @"default";
    else
        cell.textLabel.text = [dataarray objectAtIndex:indexPath.row];


    return cell;
}