3

我正在尝试在分组表视图中混合动态和静态单元格:我想得到两个部分,顶部是静态单元格,然后是一部分动态单元格(请参阅下面的屏幕截图)。我已将表格视图内容设置为静态单元格

混合动态和静态表格视图单元格

编辑

根据 AppleFreak 的建议,我将代码更改如下:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell;
    if (indexPath.section <= 1) { // section <= 1 indicates static cells
        cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]; 
    } else { // section > 1 indicates dynamic cells
        CellIdentifier = [NSString stringWithFormat:@"section%idynamic",indexPath.section];
        cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
    }
return cell;

}

但是,我的应用程序崩溃并显示错误消息

由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“UITableView 数据源必须从 tableView 返回一个单元格:cellForRowAtIndexPath:”

对于第 0 节和第 0 行。从cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]第 0 节和第 0 行返回的单元格是nil

我的代码有什么问题?我的网点有什么问题吗?我没有设置任何出口,因为我是子类UITableViewController化并且据说没有设置任何用于设置 tableview 的出口(?)。关于如何更好地做到这一点的任何建议?

在此处输入图像描述

编辑二

我在情节提要中重新创建了我的场景(请参阅上面更新的屏幕截图)并重写了视图控制器,以便从新的基础开始。我还按照 applefreak 的建议阅读了 Apple 论坛中的描述。然而,我遇到了我的第一个问题numberOfSectionsInTableView:tableView,其中我将静态部分的数量(两个)增加了一个。

  - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [super numberOfSectionsInTableView:tableView] + 1 ; }

该应用程序因错误消息而崩溃:

由于未捕获的异常“NSRangeException”而终止应用程序,原因:“*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]”

即使我遵循了 Apple 和 applefreak 的建议,为什么这段代码对我不起作用?在 iOS 6 中 tableView 可能发生了一些变化?

解决方案:我现在在他的回答中使用 AppleFreaks 代码示例让这个工作。谢谢你,AppleFreak!

编辑 III:单元格选择:

如何在混合(动态和静态单元格)单元格表视图中处理单元格选择?我什么时候打电话super,什么时候打电话self tableView?当我使用

[[super tableView] selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]

并尝试检查选定的索引路径:

UITableView *tableView = [super tableView];
if ( [[tableView indexPathForSelectedRow] isEqual:customGrowthIndexPath] ) { .. }

我得到一个返回值nil

由于我找不到错误的来源,非常感谢您的帮助

4

6 回答 6

13

对于静态单元格,您需要调用超级方法。我假设您将扩展 UITableViewController。见下文

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString *CellIdentifier = @"Cell";
    UITableViewCell *cell;

    /* Detect cell is static or dynamic(prototype) based on the index path and your settings */

    if ("Cell is prototype") 
       cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
   else if ("Cell is static")
       cell = [super tableView:tableView cellForRowAtIndexPath:indexPath];

  // Modify cell properties if you want

   return cell;
}

有关混合单元格的更多信息,请参阅苹果论坛上的混合静态和动态表格视图内容讨论。

[编辑]

如果您还没有阅读上面的苹果链接,请仔细阅读。对于动态内容,您将首次使用代码本身中的给定标识符构建单元格。下次在病房中,您将出列单元而不是构建它!这是同样的老方法。

此外,请记住静态数据源认为只有 2 个部分(例如)。你不能问它关于第 2 节的问题,因为它认为只有第 0 节和第 1 节。如果你要在表格末尾以外的任何地方插入动态内容,你需要在转发数据时对 super 撒谎源方法。例如,您的 numberOfRowsInSection: 方法应如下所示:

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if (section == 1) {
        return 1;
    }
    else if (section > 1){
        section--; // Basically you are forming sections for dynamic content
    }

    return [super tableView:tableView numberOfRowsInSection:section];
}

关键是对您的动态内容进行调整,以便静态数据源仍然获得它期望的值

[编辑]

这是完整的工作示例并经过测试。只需复制代码中的所有以下方法,它应该可以直接工作。当您有混合单元格时,您必须覆盖所有 tableview 方法。根据您的要求返回“numberOfSectionsInTableView”中静态和动态部分的总数,然后在剩余的每个方法中返回;如果有问题的部分或行是静态的,只需调用 super,如果它是动态的,则像在普通 UITableViewController 子类中那样传回相关细节。在此示例中,我只是返回 nil 或硬编码值。

有关更多信息,请查看苹果论坛上的此线程。

- (int)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 3;
}

- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section
{
    return nil;
}

- (NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section
{
    return nil;
}

- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath
{
    return NO;
}

- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath
{
    return NO;
}

-(float)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section
{
    return 44.0f;
}

- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section
{
    return 44.0f;
}

- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 44.0f;
}

- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section
{
    return nil;
}

-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section
{
    return nil;
}

-(int)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath
{
    return 5;
}

- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
    if(section == 0)
        return 2;
    if(section == 1)
        return 2;

    return 5;
}

- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if(indexPath.section <= 1)
        return [super tableView:tableView cellForRowAtIndexPath:indexPath];

    static NSString *CellIdentifier = @"Cell";


    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];

    if (cell == nil)
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];


    cell.textLabel.text = @"dynamic row";

    return cell;
}

[编辑]

您不会在 didSelectRowAtIndexPath 中调用 super。这是直截了当的。请参见下面的代码。

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
     int row = indexPath.row;
     [tableView deselectRowAtIndexPath:indexPath animated:YES];

     UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
     //process the cell
}
于 2012-10-12T12:33:06.853 回答
1

将自定义动态单元格与静态单元格一起使用的最佳且最简单的方法:

1)将容器视图放在动态表视图的标题中 2)将静态表视图分配给此容器并取消勾选“启用滚动”

于 2014-02-04T05:33:10.750 回答
0

如果没有要出列的单元格,则单元格将为 nil,因此您必须分配/初始化一个新单元格。请在尝试出队后检查单元格的值,如果为 nil,则创建一个新单元格。

于 2012-10-12T11:51:28.317 回答
0
UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:@"cellIdentify"];
if (cell == nil)
    cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellIdentify"];

只是你不调用alloc。如果您不想重用,请不要调用 dequeueReusableCellWithIdentifier。

于 2012-10-12T15:35:44.683 回答
0

谢谢applefreak的全面回答。我将在这里添加我的建议,如果您为静态部分添加虚拟部分,则不需要任何部分计算。您甚至可以在那里添加占位符元素。这样您就不必重新创建NSIndexPaths. 一件重要的事情是重写每个使用NSIndexPaths 的方法,因为这些方法会由于数组索引不匹配而导致应用程序崩溃。

此外,我完全放弃了使用出队机制并静态创建单元格,因为我拥有的动态内容没有那么多单元格。这使得tableView:cellForRowAtIndexPath:非常简单。

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    if (indexPath.section == 0)
    {
        return _locationCells[indexPath.row];
    }
    else
    {
        return [super tableView:tableView cellForRowAtIndexPath:indexPath];
    }
}

只需记住占位符部分。

于 2013-11-23T06:18:06.703 回答
0

这可以通过为将具有动态单元格的部分添加“假”部分来简单地解决。唯一需要更改的是 cellForRowAt 函数,您可以在其中将“假”部分的动态单元格出列,而不是让它们从情节提要中的内容中使用。对于其余的单元格,你调用

super.tableView(tableview, cellforRowAt: indexPath)

无需重写 tableViewController 的所有功能

于 2018-03-08T13:26:03.553 回答