如何在一个 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 永远无法到达。该表有两个部分。因此switchcase 0case 1 处理这两个部分。两者都创建并返回一个单元格。 default 永远无法到达。永远不会到达方法末尾的return。 OP 的代码比你的提议要干净得多。 谢谢 Charan,但我已经在之前的答案中解决了部分问题。我明白了你所说的@rmaddy 关于回报永远不会达到。 @rmaddy 当开关条件为真时 永远不会达到默认值。会吗?在第 0 节和第 1 节中,我将单元格 1 分配给单元格,将单元格 2 分配给单元格,并在最后将其作为返回单元格返回; break 用于仅中断开关而不是单元配置方法。所以它会到达返回单元格语句。如果我错了,你能解释一下吗

以上是关于如何在一个 tableView 中使用两个不同的自定义单元格?使用情节提要,iOS 7的主要内容,如果未能解决你的问题,请参考以下文章

我想在单个表格视图中使用来自 nib 的两个不同的自定义单元格。两个原型电池具有不同的高度

如何在 TableView 的行中应用不同的单元格样式

在不同的 ViewController 中使用相同的 TableViewCell

如何使用不同的委托和数据源方法在一个类中实现两个Tableview?

Objective-C:tableview中的2个不同的自定义单元格[关闭]

如何在 Storyboard 控制器中重用定义为原型单元的自定义 UITableViewCell