【问题标题】:How to work with two different custom cells in one tableView ? Using Storyboard, iOS 7如何在一个 tableView 中使用两个不同的自定义单元格?使用情节提要,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。必须检查我的答案并尝试过

标签: ios iphone objective-c uitableview custom-cell


【解决方案1】:

我做了一个测试,它工作正常。这些是步骤:

  1. 在storyBoard中创建UITableViewController
  2. 将 UITableViewCell 拖放到已存在的单元格下方的 UITableViewController 上
  3. 将 CellIdentifier 分配给两个单元格(我使用了 Cell1 和 Cell2)
  4. 创建 UITableViewCell 的 2 个子类(我称它们为 Cell1 和 Cell2)
  5. 创建 UITableViewController 的子类并以某种方式命名
  6. 在 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 用于仅中断开关而不是单元配置方法。所以它会到达返回单元格语句。如果我错了,你能解释一下吗
    猜你喜欢
    • 1970-01-01
    • 2014-04-01
    • 2013-07-25
    • 2012-11-01
    • 2014-02-05
    • 2012-03-03
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多