UITableView:处理混合单元格表格视图静态和动态单元格中的单元格选择 [英] UITableView: Handle cell selection in a mixed cell table view static and dynamic cells

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

问题描述

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

编辑

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

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

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

<块引用>

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

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

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

编辑二

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

 - (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView {return [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 animation: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 是原型")cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];else if ("单元格是静态的")cell = [super 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 分配] initWithStyle:UITableViewCellStyleDefault 重用标识符:CellIdentifier];cell.textLabel.text = @"动态行";返回单元格;}

不要在 didSelectRowAtIndexPath 中调用 super.这是直接的.见下面的代码.

- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath{int row = 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:处理混合单元格表格视图静态和动态单元格中的单元格选择的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆