【问题标题】:UITableView : crash when adding a section footer view in empty sectionUITableView:在空白部分添加部分页脚视图时崩溃
【发布时间】:2010-12-26 00:12:19
【问题描述】:

这是我第一次在这里提问,但我不得不说,在过去的几个月里,这个网站给了我很大的帮助(iphone-dev-wise),对此我表示感谢。

但是,对于我遇到的这个问题,我没有找到任何解决方案: 我有一个包含 2 个部分的 UITableView,第一次启动应用程序时没有行。用户可以稍后根据自己的意愿填写这些部分(这里的内容不相关)。 UITableView 在填充行时看起来不错,但在没有行时看起来很丑(2 个标题部分粘在一起,中间没有空白)。这就是为什么我想在没有行的情况下添加一个漂亮的“无行”视图。

我使用了 viewForFooterInSection:

- (CGFloat)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section {

if(section == 0)
{
    if([firstSectionArray count] == 0)
        return 44;
    else 
        return 0;
}

return 0;

}

- (UIView *)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{

    if(section == 0)
    {
        UILabel *label = [[UILabel alloc] initWithFrame:CGRectMake(200, 10, 50, 44)];
        label.backgroundColor = [UIColor clearColor];
        label.textColor = [UIColor colorWithWhite:0.6 alpha:1.0];
        label.textAlignment = UITextAlignmentCenter;
        label.lineBreakMode = UILineBreakModeWordWrap; 
        label.numberOfLines = 0;
        label.text = @"No row";
        return [label autorelease];
    }

    return nil;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return 2;
}

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section {
    if(section == 0)
    {
        return [firstSectionArray count];
    }
    return [secondSectionArray count];
}

这很好用:仅当第 0 节中没有行时才会显示页脚视图。 但是当我进入编辑模式并删除第 0 部分的最后一行时,我的应用程序崩溃了:

-[UIViewAnimation initWithView:indexPath:endRect:endAlpha:startFraction:endFraction:curve:animateFromCurrentPosition:shouldDeleteAfterAnimation:editing:] 中的断言失败 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“单元格动画停止分数必须大于开始分数”

当第 0 部分有几行时不会发生这种情况。仅当只剩下一行时才会发生这种情况。

这是编辑模式的代码:

- (void)tableView:(UITableView *)tableView commitEditingStyle:(UITableViewCellEditingStyle)editingStyle forRowAtIndexPath:(NSIndexPath *)indexPath {
    // If row is deleted, remove it from the list.
    if (editingStyle == UITableViewCellEditingStyleDelete) {
        // Find the book at the deleted row, and remove from application delegate's array.

        if(indexPath.section == 0)
        { [firstSectionArray removeObjectAtIndex:indexPath.row]; }
        else 
        { [secondSectionArray removeObjectAtIndex:indexPath.row]; }

        // Animate the deletion from the table.
        [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationBottom];


        [tableView reloadData];

    }
}

有人知道为什么会这样吗? 谢谢

【问题讨论】:

    标签: iphone uitableview


    【解决方案1】:

    看起来发生的事情是 Apple 内部的 UITableView 代码假设当您删除一行时,视图的第一部分会变短。通过使节页眉页脚突然变高以补偿最后一行,您似乎会混淆它。

    两个想法供您尝试:

    1.尝试使可选的部分页脚比即将消失的表格单元格小一到两个像素,以便动画代码执行一到两个像素的动画

    2. 当没有“真实”数据行时,不要删除表格的唯一行,而是让表格仍然有 numberOfRowsInSection 返回 1 并制作一个假的“无数据”单元格而不是在“无数据”情况下使用表格页脚。

    在这种情况下,您只需要接受 Apple 为您编写了一半的程序,并且您必须遵守您的合著者做出的一些选择,无论您喜欢与否。

    【讨论】:

    • 你是我的英雄!将“无数据”单元格缩小 2 个像素就可以了!太感谢了! (仅供参考,我已经想到了第二种解决方案,但无法使其工作)不过我仍然有一个小问题:当第 0 部分没有行时,tableview 的背景现在是白色的。我更喜欢它被填充时带有空单元格(参见此处的图片:yfrog.com/izuitableviewproblemp)。任何提示?再次感谢大卫,你让我很开心!
    【解决方案2】:
    • 制作空白部分
    • 在本节中使用表头而不是在第一节中使用页脚
    - (UIView *) tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section {
        if (section != OTHER_SECTION_INDEX) {
            return nil;
        }
        //your code here
    }
    
    - (CGFloat) tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
    {
        if (section != OTHER_SECTION_INDEX) {
            return 0;
        }
        //your code
    }
    

    【讨论】:

    • “OTHER_SECTION_INDEX”应该是什么?
    • 我的示例在 header_view 上使用 footer_view 进行更改 - 因此您需要在下面添加一个空白部分以使用 header_view。在这种情况下 OTHER_SECTION_INDEX == 0 并且 header_view 将在第 1 节中
    【解决方案3】:

    不必在 tableView 上同时调用 deleteRowsAtIndexPaths:withAnimation: 和 reloadData。

    您看到的问题是我在对deleteRowsAtIndexPaths:withAnimation: 的调用中看到的问题,因此对您来说,无论如何它永远不会到达reloadData。

    对于必须创建新单元格、管理它们、处理必须处理不同单元格的所有地方的更简单的解决方案是在处理从 0 到 1 的部分时使用 reloadSections:withAnimation:行或 1 到 0 行。

    即替换以下代码行:

            if(indexPath.section == 0)
            { [firstSectionArray removeObjectAtIndex:indexPath.row]; }
            else 
            { [secondSectionArray removeObjectAtIndex:indexPath.row]; }
    
            [tableView deleteRowsAtIndexPaths:[NSArray arrayWithObject:indexPath]
                             withRowAnimation:UITableViewRowAnimationBottom];
    

    以下

            BOOL useReloadSection;
            if (indexPath.section == 0)
            {
                [firstSectionArray removeObjectAtIndex:indexPath.row];
                useReloadSection = 0 == firstSectionArray.count;
            }
            else 
            {
                [secondSectionArray removeObjectAtIndex:indexPath.row];
                useReloadSection = 0 == secondSectionArray.count;
            }
    
            if (useReloadSection)
                [tableView reloadSections:[NSIndexSet indexSetWithIndex:indexPath.section]
                         withRowAnimation:UITableViewRowAnimationBottom];
            else
                [tableView deleteRowsAtIndexPaths:@[indexPath]
                                 withRowAnimation:UITableViewRowAnimationBottom];
    

    【讨论】:

    • 谢谢!很好的答案!
    【解决方案4】:

    我遇到了同样的崩溃,看起来是bug in the OS。

    我的具体用例与带有可折叠/可展开部分的 UITableView 有关。我需要节分隔符(这是我使用节页脚的目的),但不需要行分隔符(不能简单地使用单元格分隔符)。

    我无法通过调整节页脚的高度来解决此问题。但是切换到使用节标题就可以了,错误/崩溃不再发生。

    - (UIView *)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
    {
        CGRect frame = (CGRect){0, 0, self.view.bounds.size.width, 1};
        UIView *view = [[UIView alloc] initWithFrame:frame];
        view.backgroundColor = [UIColor commentReplyBackground];
    
        return view;
    }
    
    - (CGFloat)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
    {
        return 1.0f;
    }
    

    【讨论】:

      【解决方案5】:

      对于那些仍然需要节页脚的人,你也可以尝试将 TableView 样式更改为 UITableViewStyleGrouped。这似乎绕过了这个问题。为了获得相同的视觉外观,您只需将所有其他页脚和页眉设置为 CGFLOAT_MIN。

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多