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

时间:2023-03-25
本文介绍了UITableView:在混合单元格表视图静态和动态单元格中处理单元格选择的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着跟版网的小编来一起学习吧!

问题描述

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

编辑

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

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{静态 NSString *CellIdentifier = @"Cell";UITableViewCell *cell;if (indexPath.section <= 1) {//section <= 1 表示静态单元格单元格 = [超级 tableView:tableView cellForRowAtIndexPath:indexPath];} else {//部分 >1 表示动态单元格CellIdentifier = [NSString stringWithFormat:@"section%idynamic",indexPath.section];单元格 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];}返回单元格;}

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

<块引用>

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

对于第 0 行和第 0 行.对于第 0 行和第 0 行,从 cell = [super tableView:tableView cellForRowAtIndexPath:indexPath] 返回的单元格为 nil.p>

我的代码有什么问题?我的网点有什么问题吗?我没有设置任何插座,因为我正在继承 UITableViewController 并且据说没有任何用于设置 tableview 的插座(?).有关如何更好地做到这一点的任何建议?

编辑二

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

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

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

<块引用>

由于未捕获的异常NSRangeException"而终止应用程序,原因:'*** -[__NSArrayI objectAtIndex:]: 索引 2 超出范围 [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 的返回值.

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

解决方案

静态单元格需要调用 super 方法.我假设您将扩展 UITableViewController.见下文

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{静态 NSString *CellIdentifier = @"Cell";UITableViewCell *cell;/* 根据索引路径和您的设置检测单元格是静态的还是动态的(原型) */if ("Cell 是原型")单元格 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];else if ("单元格是静态的")单元格 = [超级 tableView:tableView cellForRowAtIndexPath:indexPath];//如果需要,修改单元格属性返回单元格;}

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

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

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

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{如果(部分 == 1){返回 1;}否则如果(部分> 1){部分 - ;//基本上你正在形成动态内容的部分}return [super tableView:tableView numberOfRowsInSection:section];}

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

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

如需更多信息,请查看苹果论坛上的 此主题.

- (int)numberOfSectionsInTableView:(UITableView *)tableView{返回 3;}- (NSString*)tableView:(UITableView *)tableView titleForHeaderInSection:(NSInteger)section{返回零;}- (NSString*)tableView:(UITableView *)tableView titleForFooterInSection:(NSInteger)section{返回零;}- (BOOL)tableView:(UITableView *)tableView canEditRowAtIndexPath:(NSIndexPath *)indexPath{返回否;}- (BOOL)tableView:(UITableView *)tableView canMoveRowAtIndexPath:(NSIndexPath *)indexPath{返回否;}-(float)tableView:(UITableView *)tableView heightForHeaderInSection:(NSInteger)section{返回 44.0f;}- (float)tableView:(UITableView *)tableView heightForFooterInSection:(NSInteger)section{返回 44.0f;}- (float)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath{返回 44.0f;}- (UIView*)tableView:(UITableView *)tableView viewForFooterInSection:(NSInteger)section{返回零;}-(UIView*)tableView:(UITableView *)tableView viewForHeaderInSection:(NSInteger)section{返回零;}-(int)tableView:(UITableView *)tableView indentationLevelForRowAtIndexPath:(NSIndexPath *)indexPath{返回 5;}- (int)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section{如果(部分 == 0)返回 2;如果(部分 == 1)返回 2;返回 5;}- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath{if(indexPath.section <= 1)return [super tableView:tableView cellForRowAtIndexPath:indexPath];静态 NSString *CellIdentifier = @"Cell";UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];如果(单元格 == 零)单元格 = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];cell.textLabel.text = @"动态行";返回单元格;}

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

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{int 行 = indexPath.row;[tableView deselectRowAtIndexPath:indexPath 动画:YES];UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];//处理单元格}

I am trying to mix dynamic and static cells in a grouped table view: I would like to get two sections with static cells at the top followed by a section of dynamic cells (please refer to the screenshot below). I have set the table view contents to static cells.

Edit

Based on AppleFreak's advice I have changed my code as follows:

- (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;

}

However, my app crashes with error message

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

for section 0 and row 0. The cell returned from cell = [super tableView:tableView cellForRowAtIndexPath:indexPath] for section 0 and row 0 is nil.

What is wrong with my code? Could there be any problems with my outlets? I haven't set any outlets because I am subclassing UITableViewController and supposedly do not any outlets for tableview to be set (?). Any suggestions on how to better do it?

Edit II

I have recreated my scene in storyboard (please refer to my updated screen shot above) and rewritten the view controller in order to start from a new base. I have also read the description in Apple's forum as applefreak suggested. However, I run in my first problem with the method numberOfSectionsInTableView:tableView, in which I increment the number of static sections (two) by one.

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

The app crashed with the error message:

Terminating app due to uncaught exception 'NSRangeException', reason: '*** -[__NSArrayI objectAtIndex:]: index 2 beyond bounds [0 .. 1]'

Why is this code not working for me even though I followed Apple's and applefreak recommendations? It is possible that the tableView has changed a bit in iOS 6?

Solution: I got this to work now using AppleFreaks code sample in his answer below. Thank you, AppleFreak!

Edit III: Cell Selection:

How can I handle cell selection in a mixed (dynamic and static cells) cell table view? When do I call super and when do I call self tableView? When I use

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

and try to check for the selected index paths with:

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

I get an return value of nil.

As I can't find the source of my error, I really would appreciate your help

解决方案

For static cells you need to call super method. I presume that you will be extending UITableViewController. See below

- (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;
}

Also for more information on mixing cells see Mixing static and dynamic table view content discussion on apple forums.

[EDIT]

If you haven't read apple link above then please do so carefully. For dynamic content you will build the cell first time with the given identifier in the code itself. Next time on wards you will dequeue the cell rather than building it! It's the same old way.

Moreover, remember that the static data source thinks there are only 2 sections(for example). You can't ask it about section 2, because it thinks there are only sections 0 and 1. If you're going to be inserting dynamic content anywhere but the end of the table, you need to lie to super when you forward the data source methods. Your numberOfRowsInSection: method, for example, should look something like this:

- (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];
}

The key is making the adjustment for your dynamic content so that the static data source still gets the values it expects

[EDIT]

Here is the complete working example and tested. Just copy past all of following methods in your code and it should work straight way. You have to override all the tableview methods when you have mixed cells. Return the total number of static and dynamic sections in "numberOfSectionsInTableView" as per your requirements, and then in each of the remaining methods; if the section or row in question is static just call through to super, if it's dynamic pass back the relevant details as you would in a normal UITableViewController subclass. In this example, I am simply returning nil or hard coded values.

For more information check this thread on apple forums.

- (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;
}

[EDIT]

You don't call super in didSelectRowAtIndexPath. It's straight forward. See below code.

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

     UITableViewCell *selectedCell = [tableView cellForRowAtIndexPath:indexPath];
     //process the cell
}

这篇关于UITableView:在混合单元格表视图静态和动态单元格中处理单元格选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持跟版网!

上一篇:如何在 iOS 中删除 Safari 中的地址栏? 下一篇:无法更改 Xcode 4.5 中的目标成员身份可见性

相关文章