如何在一个 tableView 中使用两个不同的自定义单元格?使用情节提要,iOS 7
Posted
技术标签:
【中文标题】如何在一个 tableView 中使用两个不同的自定义单元格?使用情节提要,iOS 7【英文标题】:How to work with two different custom cells in one tableView ? Using Storyboard, iOS 7 【发布时间】:2014-03-05 04:28:19 【问题描述】:我有两个自定义单元格。我想在我的UITableView
中显示 2 个部分。第一部分显示第一个自定义单元格,第二部分显示从核心数据中提取的对象列表。
我应该如何实现“cellForRowAtIndexpath”方法?
这是我的一些代码:
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
// Return the number of sections.
return 2;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
// Return the number of rows in the section.
if (section == 0)
return 1;
else if (section == 1)
//gastos is an array
return [self.gastos count];
return 0;
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
switch (indexPath.section)
case 0:
SaldoCelda *cell1 = [tableView dequeueReusableCellWithIdentifier:@"Cell1" forIndexPath:indexPath];
return cell1;
case 1:
static NSString *CellIdentifier = @"Cell";
CeldaGasto *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSManagedObject *gasto = [self.gastos objectAtIndex:indexPath.row];
[cell.monto setText:[NSString stringWithFormat:@"%@ AR$", [gasto valueForKey:@"monto"]]];
[cell.categoria setText:[NSString stringWithFormat:@"%@", [gasto valueForKey:@"categoria"]]];
[cell.fecha setText:[NSString stringWithFormat:@"%@", [gasto valueForKey:@"fecha"]]];
return cell;
default:
break;
return 0;
这是我收到的错误消息:
断言失败 -[UITableView _configureCellForDisplay:forIndexPath:], /SourceCache/UIKit_Sim/UIKit-2903.23/UITableView.m:6246 2014-03-05 01:02:57.181 Spendings[2897:70b] * 由于未捕获的异常“NSInternalInconsistencyException”而终止应用程序,原因:“UITableView 数据源必须从 tableView:cellForRowAtIndexPath 返回一个单元格:”
感谢您的帮助!
【问题讨论】:
读取错误。您正在为您的cellForRowAtIndexPath:
方法返回 nil
。要么是 case 0 要么是 case 1。使用调试器,看看哪个是问题所在。
顺便说一句 - 一点旁注 - 对于以 return
结尾的情况,您的 switch
中不需要 break
语句。在这些情况下,将永远无法到达 break
语句。
你是对的!方法结束时返回0可以吗?切换结束后?
实际上,cellForRowAtIndexPath
末尾的return 0;
应该是return nil;
,但从技术上讲,它们是一回事。无论如何,return 0
将永远无法到达。
@JuanM。必须检查我的答案并尝试过
【参考方案1】:
我做了一个测试,它工作正常。这些是步骤:
-
在storyBoard中创建UITableViewController
将 UITableViewCell 拖放到已存在的单元格下方的 UITableViewController 上
将 CellIdentifier 分配给两个单元格(我使用了 Cell1 和 Cell2)
创建 UITableViewCell 的 2 个子类(我称它们为 Cell1 和 Cell2)
创建 UITableViewController 的子类并以某种方式命名
在 cellForRowAtIndexPath 方法中:
static NSString *CellIdentifier = @"Cell1";
static NSString *CellIdentifier1 = @"Cell2";
switch (indexPath.section)
case 0:
Cell1 *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
return cell;
break;
case 1:
Cell2 *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier1 forIndexPath:indexPath];
return cell;
break;
default:
break;
return nil;
如您所见,实现与您的相同
我可以重现您的错误的唯一方法是在 switch 块中返回 nil 并且 dequeueReusableCellWithIdentifier 的文档说:
这个方法总是返回一个有效的单元格。
即使您弄乱了单元格标识符,您仍然不会收到您发布的错误。所以我的结论是:
重新启动、清理项目、重新启动模拟器或类似的事情会导致您无法根据文档的情况...
【讨论】:
【参考方案2】:除了您要为其中一个单元格返回 nil
之外,您在 numberOfRowsInSection
中也有问题,您正在为第 1 节返回 0 行!!,尽管您希望 cellForRowAtIndexPath
中的此部分中有行.
【讨论】:
虽然numberOfRowsInSection:
的实现正如您所指出的那样不正确,但这实际上与崩溃无关。但它确实将cellForRowAtIndexPath:
中的问题缩小到case 0:
代码。
嗯,100% 同意 ;) 但还有一个问题他应该处理。
好的,我刚刚解决了这个问题,但我的问题仍然存在。第 0 部分只有我想要的一行,第 1 部分有“gastos”的计数。
首先该表不是与您的问题无关的“静态单元格”内容(我猜是忽略),其次您需要为第 2 节创建一个原型单元格并将其注册为“单元格" 或在您的 cellForRowAtIndexPath
中初始化它。
很高兴,单元格高度是另一回事,使用委托更改它:- (CGFloat)tableView:(UITableView *)tableView heightForRowAtIndexPath:(NSIndexPath *)indexPath if (indexpathe.section == 0 && indexpathe.row == 0) 返回 50.0;返回 100; 【参考方案3】:
您可以在一个 xib 中创建一组单元格,并使用其标识符在 cellForRowAtindex 中获取它。现在你可以设置它的属性和数据了。
static NSString *CellIdentifier = @"MyCellIdentifier";
MyCell *cell = (MyCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil)
NSArray *nib = [[NSBundle mainBundle] loadNibNamed:CellIdentifier owner:self options:nil];
cell = (MyCell *)[nib objectAtIndex:0];
cell1=(MyCell *)[nib objectAtIndex:1];
【讨论】:
我认为使用 XIB 文件已经过时了,在 xCode 5 和 ios 7 中,一切都适用于故事板。 我实际上使用 XIB 文件来创建单元格,在进行单元格设计时,加载更简单,更专注。但我知道你只想使用 Storyboard 也许你还是应该试一试。 你可以在故事板的帮助下做同样的事情。如果是情节提要,您必须从情节提要文件中获取单元格的笔尖。【参考方案4】:试试这个我正在修改你的代码
- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
// Return the number of sections.
return 2;
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
// Return the number of rows in the section.
if (section == 0)
return 1;
else if (section == 2)
//gastos is an array
return [self.gastos count];
//return 0; you should not write this because at the end of execution of this method it will return 0
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
static NSString *CellIdentifier = @"Cell";
UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:CellIdentifier];
switch (indexPath.section)
case 0:
SaldoCelda *cell1 = [tableView dequeueReusableCellWithIdentifier:@"Cell1" forIndexPath:indexPath];
cell=cell1;
break;
case 1:
static NSString *CellIdentifier = @"Cell";
CeldaGasto *cell2 = [tableView dequeueReusableCellWithIdentifier:CellIdentifier forIndexPath:indexPath];
NSManagedObject *gasto = [self.gastos objectAtIndex:indexPath.row];
[cell.monto setText:[NSString stringWithFormat:@"%@ AR$", [gasto valueForKey:@"monto"]]];
[cell.categoria setText:[NSString stringWithFormat:@"%@", [gasto valueForKey:@"categoria"]]];
[cell.fecha setText:[NSString stringWithFormat:@"%@", [gasto valueForKey:@"fecha"]]];
cell=cell2;
break;
default:
break;
return cell;
//return 0; remove this in your code
希望这会有所帮助
【讨论】:
这些更改都不需要,它实际上使代码更加混乱。而且这些都不能解决问题。 @rmaddy 哪部分代码让你感到困惑?返回0;表示您将 nil 返回到单元格和行... 我并不困惑。return
永远无法到达。该表有两个部分。因此switch
的case 0
和case 1
处理这两个部分。两者都创建并返回一个单元格。 default
永远无法到达。永远不会到达方法末尾的return
。 OP 的代码比你的提议要干净得多。
谢谢 Charan,但我已经在之前的答案中解决了部分问题。我明白了你所说的@rmaddy 关于回报永远不会达到。
@rmaddy 当开关条件为真时 永远不会达到默认值。会吗?在第 0 节和第 1 节中,我将单元格 1 分配给单元格,将单元格 2 分配给单元格,并在最后将其作为返回单元格返回; break 用于仅中断开关而不是单元配置方法。所以它会到达返回单元格语句。如果我错了,你能解释一下吗以上是关于如何在一个 tableView 中使用两个不同的自定义单元格?使用情节提要,iOS 7的主要内容,如果未能解决你的问题,请参考以下文章
我想在单个表格视图中使用来自 nib 的两个不同的自定义单元格。两个原型电池具有不同的高度
在不同的 ViewController 中使用相同的 TableViewCell
如何使用不同的委托和数据源方法在一个类中实现两个Tableview?