UITableView有两种类型的可重用单元格无法正常工作

时间:2011-12-14 01:21:44

标签: iphone objective-c xcode uitableview

我正在尝试创建一个使用两种类型的单元格的表格视图 - 默认和副标题。

我尝试使用一个可重复使用的单元格(*cell),它似乎工作正常,直到我到达屏幕下方的底部单元格 - 当它进入视图时它是第一个可见单元格的副本。

我认为我可以尝试添加第二种类型的单元格(*cellB),当我这样做时似乎解决了问题但是它会经常崩溃并出现以下错误:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'UITableView dataSource must return a cell from tableView:cellForRowAtIndexPath:'

我知道我做错了,我很确定我没有正确实施可重复使用的细胞,但经过几天的挫折后,我真的很感激一些建议。

P.S。我搜索了许多以前的帖子,但似乎没有涉及在同一个桌子上使用两种类型的单元格的问题。

提前致谢。

- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
 return 1;
}

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
return  5; 
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

 UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCell"];

 UITableViewCell *cellB = [tableView dequeueReusableCellWithIdentifier:@"UITableViewCellB"];


switch (indexPath.section) {


 case 0:
     if (cell == nil) {
         // The only subtitle cell
         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleSubtitle
                                      reuseIdentifier:@"UITableViewCell"]; 

     }

        [[cell textLabel] setText:title];
        [[cell textLabel] setTextColor:[UIColor whiteColor]]; 
        [[cell detailTextLabel] setText:[NSString stringWithFormat:@"Entry: £%@",price]];
        [[cell detailTextLabel] setTextColor:[UIColor colorWithWhite:1.0 alpha:.8]]; 


        cell.selectionStyle = UITableViewCellSelectionStyleNone; 

     break;

 case 1:
     if (cell == nil) {

         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:@"UITableViewCell"]; 

         UIView *cellBackView = [[UIView alloc] initWithFrame:CGRectZero];
         cellBackView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:@"PhotoFrame.png"]];
         cell.backgroundView = cellBackView;

     }

     [lImage setFrame:CGRectMake(0, 23, 320, 200)];

     [cell.contentView addSubview:lImage];

     break;

 case 2:
     if (cell == nil) {

         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:@"UITableViewCell"]; 

         UIView *cellBackView = [[UIView alloc] initWithFrame:CGRectZero];
         cellBackView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:@"PaperTop.png"]];
         cell.backgroundView = cellBackView;

     }

     break;

 case 3:
     if (cell == nil) {

         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:@"UITableViewCell"]; 


         UIView *cellBackView = [[UIView alloc] initWithFrame:CGRectZero];
         cellBackView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:@"Paper.png"]];
         cell.backgroundView = cellBackView;

     }

     break;

 case 4:
     // I'm pretty sure this bit is wrong but if I use (cell == nil) the first cell is shown instead
     if (cellB == nil) {

         cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                      reuseIdentifier:@"UITableViewCellB"]; 

         UIView *cellBackView = [[UIView alloc] initWithFrame:CGRectZero];
         cellBackView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:@"PaperBottom.png"]];
         cell.backgroundView = cellBackView;

     }

     break;

 default:
     break;
} 

 return cell; 
}

4 个答案:

答案 0 :(得分:2)

如果cellB 不是 null,您仍然会返回cell而不是cellB

编辑:

要修复,请在case 4块中添加代码,如下所示:

case 4:
    if (cellB == nil) {
        // No changes in here
    }
    else {             //
        cell = cellB;  // Add these 3 lines
    }                  //
    break;

答案 1 :(得分:2)

对于需要填充的每个单元格,调用此方法一次。如果您滚动表格,行将离开屏幕并与其重用标识符排队。当行滚动到表格上时,调用此方法以在单元格变为可见时填充单元格。

首先,您只想在每次调用此方法时将一个单元格出列。通过将类型为UITableViewCell' and UITableViewCellB'的单元格出列,您将出列一个不会被使用的单元格。因此,您需要在排队之前确定所需的单元格类型,然后将正确的类型(通过其重用标识符)出列。

其次,单元格排队机制的目的是让您不必每次在视图中显示时自定义单元格外观。如果具有该类型外观的单元已经在队列中,那么它应该已经从已经设置的队列中出来,并且您只需要将数据放入其中。这是为了提高性能(速度),但在您的情况下可能没有太大区别。

我可能错了,如果我这样做,我会更正我的答案,但错误信息可能是因为numberOfSections返回的部分数和/或{{返回的数字或行数1}}不正确,与数据源不匹配。它正在尝试访问不存在的数据源元素。

您使用的是哪种数据源,是否可以显示numberOfRowsInSection:numberOfSections的代码?

更正更正

numberOfRowsInSection:

答案 2 :(得分:0)

cgull是正确的。 用这个替换案例4:

case 4:
  if (cellB == nil) {

     // assign to the correct cell
     cellB = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:@"UITableViewCellB"]; 

     UIView *cellBackView = [[UIView alloc] initWithFrame:CGRectZero];
     cellBackView.backgroundColor = [UIColor colorWithPatternImage: [UIImage imageNamed:@"PaperBottom.png"]];
     cell.backgroundView = cellBackView;

 }

 return cellB;  // <--- return the correct cell

答案 3 :(得分:0)

正如cgull所指出的,当[indexPath section]4时,您正在初始化cellB,但仍会返回cell,其中可能有也可能没有有效的单元格它

无论通过switch采取的路径如何,您都需要有一个变量来保存您要返回的单元格:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{

    NSString identifier = @"UITableViewCell";
    if( [indexPath section] == 4 ){
        identifier = @"UITableViewCellB";
    }
    // Try to dequeue the appropriate cell kind
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:identifier];


    switch (indexPath.section) {

            //other cases...

        case 4:
            // You now have only one variable that can possibly hold a cell.
            // If section is 4, it's either nil or a UITableViewCellB kind.
            if (cell == nil) {

                cell = [[UITableViewCell alloc]initWithStyle:UITableViewCellStyleDefault
                                  reuseIdentifier:@"UITableViewCellB"];
                // Set up new cell

            }

            break;

        default:
            break;
    } 

    return cell; 
}