UITableView:处理混合单元格表中的单元格选择视图静态和动态单元格

Ale*_*exR 3 objective-c uitableview ios ios5

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

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

编辑

基于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;

}
Run Code Online (Sandbox Code Playgroud)

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

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

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

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

在此输入图像描述

编辑二

我在故事板中重新创建了我的场景(请参阅我上面更新的屏幕截图)并重新编写视图控制器以便从新基础开始.我也在Apple的论坛中阅读了applefreak建议的描述.但是,我运行的第一个问题是使用该方法numberOfSectionsInTableView:tableView,其中我将静态部分(两个)的数量增加一个.

  - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {
    return [super numberOfSectionsInTableView:tableView] + 1 ; }
Run Code Online (Sandbox Code Playgroud)

该应用程序崩溃并显示错误消息:

由于未捕获的异常'NSRangeException'终止应用程序,原因:'*** - [__ NSArrayI objectAtIndex:]:索引2超出边界[0 .. 1]'

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

解决方案:我现在使用AppleFreaks代码示例在下面的答案中使用它.谢谢,AppleFreak!

编辑III:细胞选择:

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

[[super tableView] selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]
Run Code Online (Sandbox Code Playgroud)

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

UITableView *tableView = [super tableView];
if ( [[tableView indexPathForSelectedRow] isEqual:customGrowthIndexPath] ) { .. }
Run Code Online (Sandbox Code Playgroud)

我得到了一个返回值nil.

由于我找不到错误的来源,我真的很感激你的帮助

app*_*eak 13

对于静态单元,您需要调用super方法.我假设您将扩展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;
}
Run Code Online (Sandbox Code Playgroud)

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

[编辑]

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

此外,请记住,静态数据源认为只有2个部分(例如).你不能问第2部分,因为它认为只有第0和第1部分.如果你要将动态内容插入表格的末尾,你需要在转发数据时说谎超级源方法.例如,您的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];
}
Run Code Online (Sandbox Code Playgroud)

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

[编辑]

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

有关更多信息,请在Apple论坛上查看主题.

- (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;
}
Run Code Online (Sandbox Code Playgroud)

[编辑]

你不要在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
}
Run Code Online (Sandbox Code Playgroud)