UITableView:处理混合单元格表格中的单元格select查看静态和dynamic单元格
我想在组合的表格视图中混合dynamic和静态单元格:我想在静态单元格的顶部有两个部分,后面跟着一部分dynamic单元格 (请参阅下面的屏幕截图)。 我已经将表格视图内容设置为静态单元格 。
编辑
基于AppleFreak的build议,我改变了我的代码如下:
- (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; }
但是,我的应用程序崩溃与错误信息
终止应用程序由于未捕获的exception“NSInternalInconsistencyException”,原因:'UITableView数据源必须从tableView:cellForRowAtIndexPath:'返回一个单元格
对于第0行和第0行。对于第0行和第0行,从cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]
格返回的cell = [super tableView:tableView cellForRowAtIndexPath:indexPath]
nil
。
我的代码有什么问题? 我的店可能有问题吗? 我没有设置任何网点,因为我是UITableViewController
子类,并且应该没有设置tableview的任何网点(?)。 任何build议如何更好地做到这一点?
编辑二
我已经在故事板中重新创build了我的场景(请参阅上面我更新的屏幕截图),并重写了视图控制器以便从新的基础开始。 我也读过苹果论坛的描述,因为applefreakbuild议。 然而,我运行在第一个问题的方法numberOfSectionsInTableView:tableView
,其中我增加了一个静态部分(两个)的数量。
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView { return [super numberOfSectionsInTableView:tableView] + 1 ; }
该应用程序崩溃与错误消息:
由于未捕获的exception'NSRangeException',原因:'*** – [__ NSArrayI objectAtIndex:]:index 2 beyond bounds [0..1]'
为什么这个代码不适合我,即使我遵循了苹果和applefreak的build议? 有可能在iOS 6中tableView有所改变?
解决scheme :我现在在下面的答案中使用了AppleFreaks代码示例。 谢谢,AppleFreak!
编辑三:单元格select:
如何处理混合(dynamic和静态单元格)单元格表格视图中的单元格select ? 我什么时候打super
电话,什么时候打电话给self tableView
? 当我使用
[[super tableView] selectRowAtIndexPath:indexPath animated:NO scrollPosition:UITableViewScrollPositionNone]
并尝试检查所选的索引path:
UITableView *tableView = [super tableView]; if ( [[tableView indexPathForSelectedRow] isEqual:customGrowthIndexPath] ) { .. }
我得到的返回值nil
。
由于找不到我的错误来源,我真的很感谢你的帮助
对于静态单元,你需要调用超级方法。 我认为你将会扩展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; }
有关混合单元格的更多信息,请参阅在苹果论坛上混合静态和dynamic表格视图内容讨论。
[编辑]
如果您还没有阅读上面的苹果链接,请仔细阅读。 对于dynamic内容,您将首先使用代码中的给定标识符来构build单元格。 下一次在病房,你会出院的细胞,而不是build设! 这是旧的方式。
此外,请记住,静态数据源认为只有2个部分(例如)。 你不能问第二部分,因为它认为只有部分0和1.如果你打算在dynamic内容中插入dynamic内容,但是在表的最后,你需要在转发数据的时候撒谎源方法。 例如,您的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]; }
关键是对dynamic内容进行调整,以便静态数据源仍然可以获得预期的值
[编辑]
这里是完整的工作示例并进行了testing。 只要复制代码中的以下所有方法,就可以直接使用。 混合单元格时,必须覆盖所有的tableview方法。 按照您的要求返回“numberOfSectionsInTableView”中静态和dynamic部分的总数,然后返回其余的每个方法; 如果所讨论的部分或行是静态的,只需调用super即可,如果它是dynamic的,就像在普通的UITableViewController子类中那样传回相关的细节。 在这个例子中,我只是返回零或硬编码的值。
欲了解更多信息,请在苹果论坛上查看此主题。
- (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 }
使用静态单元自定义dynamic单元的最佳和最简单的方法:
1)将容器视图放置在dynamic表格视图的标题中2)将静态表格视图分配给该容器并取消“滚动已启用”
如果没有单元出队,那么单元将是零,因此你必须分配/初始化一个新单元。 请尝试退出一个单元格后检查单元格的值,并创build一个新的单元格,如果它是零。
谢谢applefreak的全面回答。 我将在这里添加我的build议,如果为静态部分添加虚拟部分,则不需要任何部分计算。 你甚至可以在那里添加占位符元素。 这样你就不必重新创buildNSIndexPath
。 一个重要的事情是重写每个使用NSIndexPath
的方法,因为这会由于数组索引不匹配而导致应用程序崩溃。
另外,我完全放弃了使用出列机制,静态地创build了单元格,因为我没有那么多的单元格。 这使得tableView:cellForRowAtIndexPath:
非常简单。
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { if (indexPath.section == 0) { return _locationCells[indexPath.row]; } else { return [super tableView:tableView cellForRowAtIndexPath:indexPath]; } }
只要记住占位符部分。
UITableViewCell *cell = [self dequeueReusableCellWithIdentifier:@"cellIdentify"]; if (cell == nil) cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"cellIdentify"];
只要你不拨打分配。 如果你不想重用,只是不要调用dequeueReusableCellWithIdentifier。