2013-02-27 63 views
3

似乎有很多关于此问题的问题,但我无法使用任何人的答案,所以希望有人可以回顾一下我是如何做到这一点的。我正在尝试使用。我有两个自定义的UITableViewCells,它们现在对它们只有一个BOOL属性,这就是它的样式。自定义UITableViewCells没有在UITableView上重复使用

在我的cellForRowAtIndexPath方法基于什么类型的数据回来我正在设计我的细胞。如果数据是“月”标题,那么它就是一个看起来很长的细胞,如果它是“新闻”,它将成为一个更大的白色细胞。

enter image description here

当表加载一切看起来很大,但如果我向下滚动,以创造更多的细胞,达到细胞被重建,并最终滚动减慢,因为我跑出来的内存中,然后向后滚动。

当我设置中断点时dequeueReusableCellWithIdentifier总是返回零,所以我的细胞不会重用,这似乎是一个问题。

在这张图片中可以看到,细胞越来越堆叠在彼此的顶部和搞砸:

enter image description here

这里我我的代码:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    static NSString *NewsCellIdentifer = @"NewsCellIdentifier"; 
    static NSString *MonthCellIdentifier = @"MonthCellIdentifier"; 


    NSUInteger row = [indexPath row]; 
    NewsItem *item = [self.newsArray objectAtIndex:row]; 

    if (item.IsMonth == YES) 
    { 
     NewsMonthUITableViewCell *cell = [self.mytableView dequeueReusableCellWithIdentifier:MonthCellIdentifier]; 

     if (cell == nil) 
     { 
      cell = [[NewsMonthUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:MonthCellIdentifier]; 
     } 

     // This handles any other "date" cells to allow for different spacing styles. 
     if (item.IsMonth) 
     { 
      UIImageView *av = [[UIImageView alloc] initWithFrame:CGRectMake(0, 10, 400, 20)]; 
      av.backgroundColor = [UIColor clearColor]; 
      av.opaque = NO; 
      av.image = [UIImage imageNamed:@"month-bar-bkgd.png"]; 
      UILabel *monthTextLabel = [[UILabel alloc] initWithFrame:CGRectMake(10, 10, 150, 20)];; 
      CGFloat font = 11.0f; 
      monthTextLabel.font = [BVFont HelveticaNeue:&font]; 
      monthTextLabel.backgroundColor = [UIColor clearColor]; 
      monthTextLabel.font = [BVFont HelveticaNeue:&font]; 
      monthTextLabel.textColor = [BVFont WebGrey]; 
      monthTextLabel.text = item.Title; 

      cell.backgroundColor = [UIColor clearColor]; 
      [cell.contentView addSubview:av]; 
      [cell.contentView addSubview:monthTextLabel]; 
     } 

     return cell; 

    } 
    else 
    { 
     NewsUITableViewCell *cell = [self.mytableView dequeueReusableCellWithIdentifier:NewsCellIdentifer]; 

     if (cell == nil) 
     { 
      cell = [[NewsUITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:NewsCellIdentifer]; 
     } 

     cell.contentView.backgroundColor = [UIColor clearColor]; 

     UIView *whiteRoundedCornerView = [[UIView alloc] initWithFrame:CGRectMake(10,10,300,100)]; 
     whiteRoundedCornerView.backgroundColor = [UIColor whiteColor]; 
     whiteRoundedCornerView.layer.masksToBounds = NO; 
     whiteRoundedCornerView.layer.cornerRadius = 3.0; 
     whiteRoundedCornerView.layer.shadowOffset = CGSizeMake(-1, 1); 
     whiteRoundedCornerView.layer.shadowOpacity = 0.5; 

     [cell.contentView addSubview:whiteRoundedCornerView]; 
     [cell.contentView sendSubviewToBack:whiteRoundedCornerView]; 
     [cell.contentView addSubview:[self NewsItemThumbnailView:item]]; 
     [cell.contentView addSubview:[self NewsItemTextView:item]]; 
     [cell.contentView addSubview:[self NewsItemCornerIconIndicatorView:item]]; 

     return cell; 

    } 

    return nil; 

} 

感谢您的任何援助或咨询!

+0

你在使用故事板吗? – 2013-02-27 16:55:11

+1

您是否正在使用动态原型的故事板?如果是,请检查属性检查器中的每个单元格“标识符”是否设置正确。另外,如果你不使用故事板和动态原型,你创建和添加子视图的代码应该放在你的if(cell == nil)块中。我的建议是使用动态原型的Storyboard并在IB中的单元格中进行自定义。 – 2013-02-27 16:57:13

+0

我正在使用Storyboard,但我没有使用Prototyped单元格或在故事板中设计我的单元格。我只是将我的TableView放在屏幕上,但以编程方式完成剩下的工作。 – Flea 2013-02-27 16:57:36

回答

2

因为你没有动态原型使用故事板,那么你需要将你的代码创建并添加子视图在你的if (cell==nil)块中,否则所有的子视图会在每次tableview单元被重新使用时再次被添加。

继续前行,我的建议是使用动态原型的Storyboard(带有子类UITableViewCells),并执行在IB中的单元格中定制

1

将您的单元格转换为Customcells,并使用tableView查看下面的示例。

NewsMonthUITableViewCell *cell = (NewsMonthUITableViewCell *)[tableView dequeueReusableCellWithIdentifier:MonthCellIdentifier]; 
    NewsUITableViewCell *cell =(NewsUITableViewCell*) [tableView dequeueReusableCellWithIdentifier:NewsCellIdentifer]; 

使用动态原型细胞,细胞的原型是有小区分配中没有要求&检查是否正确cellIdentifier。

在故事板上创建两个原型单元&给他们不同的cellIdentifier,在你的情况下NewsCellIdentifer & MonthCellIdentifier。请确保NewsCellIdentifer的拼写正确,因为您错过了NewsCellIdentifer的i

+0

Ravindra,谢谢你的回应。我只是尝试过,但仍然有相同的行为。 – Flea 2013-02-27 17:00:17

+0

从桌面删除自我查看 – 2013-02-27 17:03:19

+0

我认为它是因为self.myTableView,删除它并只使用tableView – 2013-02-27 17:05:25

1

有趣的问题。你说你的信元出队返回零。这是否被断点或日志证实?或者这仅仅是你发布的图片的扣除?

在我看来,可能会有另一个元凶堆叠在一起而不被重用的问题的罪魁祸首。

我可以看到,每次滚动单元格时,都会创建whiteRoundedCornerView并将其添加到单元格中。即使这不是你的问题的原因,这肯定是一个问题。你没有正确地创建单元格。您必须将此代码放入if(cell == nil)块中。事实上,几乎所有位于块外的代码都需要进入它。然后任何设置文本或图像值的代码都应该出现在块之外。我看到有人已经提出了这个建议,但它并没有让你满意。我只是再次强调它仍然是错误的,如果你想修复你的应用程序,你需要解决这个问题。 (顺便说一下漂亮的应用程序)。

此外,如果我可以就你的代码的其他方面提出建议。您自定义编码的标题,并没有使用实际的部分标题。这对我来说是非常奇怪的。另外,你有一个冗余的“if(item。因为一个已经在另一个块中,它总是一个月的项目

+0

顺便说一句,如果我的帖子不清楚,whiteRoundedCornerView的堆叠是什么导致你在屏幕截图中显示的视觉工件。 – 2013-02-27 17:35:38

+0

我iPhone上的愚蠢刷新让我错过了这个已经为你工作的事实。而是写了这个长时间的回应。 – 2013-02-27 17:38:19

+0

感谢eddieios,你是正确的,我需要把代码放在(cell == nil)块中!感谢您抽出宝贵时间回答,我将您的答案提高为有用! – Flea 2013-02-28 19:25:32

0

我在iOS 7和storyboard上有同样的问题,而我从来没有在老版本的Xcode-SDK版本上使用相同的代码出现此问题,而tr从stackoverflow许多建议,我无法修复它,并猜测什么?!苹果的TableView Programming Guide有很好的解释指南。 甚至不需要使用cell==nil

所以我把这里的指示,希望它可以帮助别人:

若要使用故事板将被重复使用得当,可以采取两种不同的approacesh定制的tableview细胞。我个人更喜欢第一个更直接的,但我把这两个解决方案放在这里。

第一种方法

  1. 创建一个使用主从应用模板的项目,并选择使用故事板选项。
  2. 在故事板画布上,选择主视图控制器。
  3. 在Identity检查器中,验证Class是否设置为自定义MasterViewController类。
  4. 选择主视图控制器内部的表格视图。
  5. 在属性检查器中,验证内容弹出式菜单是否设置为动态原型。
  6. 选择原型单元格。
  7. 在属性检查器中,在样式弹出菜单中选择自定义。
  8. 在标识符文本字段中输入重用标识符。 这是与发送到dequeueReusableCellWithIdentifier:消息中的表视图相同的重用标识符。
  9. 在Accessory弹出菜单中选择Disclosure Indicator。
  10. 将库中的对象拖动到单元格上。 对于此示例,拖动两个标签对象并将它们放在靠近单元格末端的位置(为附件视图留出空间)。
  11. 选择对象并设置其属性,大小和自动修改特征。

为此过程的编程部分设置的一个重要属性是每个对象的tag属性。在Attributes inspectorView部分中查找此属性,并为每个对象分配一个唯一的整数。

现在编写您通常会写入的代码以获取表视图的数据。 (在这个例子中,你需要的唯一数据就是每个单元格的行号。)实现数据源方法的tableView:的cellForRowAtIndexPath:创建从原型一个新的细胞,并用数据填充它,在类似这样的代码的方式:

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
{ 
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"]; 

    UILabel *label; 

    label = (UILabel *)[cell viewWithTag:1]; 
    label.text = [NSString stringWithFormat:@"%d", indexPath.row]; 

    label = (UILabel *)[cell viewWithTag:2]; 
    label.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row]; 

    return cell; 
} 

有此代码需要注意的几个方面:

  • 您分配给原型单元格的字符串标识符是您传递给dequeueReusableCellWithIdentifier:中的表格视图的字符串。
  • 因为原型单元格是在故事板中定义的,所以dequeueReusableCellWithIdentifier:方法总是返回一个有效的单元格。您无需检查返回值nil并手动创建单元格。
  • 代码通过调用viewWithTag:传入其标签整数来获取单元中的标签。然后它可以设置标签的文本内容。

第二种方法

如果你不喜欢使用标签,您可以使用另一种方法设置单元格中的内容。为要设置的对象定义一个带有插座属性的自定义UITableViewCell子类。在故事板中,将新类与原型单元相关联,并将出口连接到单元中的相应对象。

要使用网点的自定义单元格内容

  1. 名为MyTableViewCell的Objective-C类添加到您的项目。
  2. 下面的代码添加到所述接口中MyTableViewCell.h

    @interface MyTableViewCell:的UITableViewCell

    @属性(非原子,弱)IBOutlet中的UILabel * firstLabel; @property(非原子,弱)IBOutlet UILabel * secondLabel; @end

  3. 下面的代码添加到实施MyTableViewCell.m

    @synthesize firstLabel,secondLabel;

  4. 下面的代码行添加到实现该数据源的源文件:

    #进口“MyTableViewCell.h”

  5. 使用Identity inspector原型细胞的类设置为MyTableViewCell

  6. 使用Connections检查器将原型单元中的两个出口连接到它们对应的标签。 enter image description here

  7. 实现数据源的方法tableView:cellForRowAtIndexPath:

    -(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath { 
    MyTableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:@"MyIdentifier"]; 
    
    cell.firstLabel.text = [NSString stringWithFormat:@"%d", indexPath.row]; 
    cell.secondLabel.text = [NSString stringWithFormat:@"%d", NUMBER_OF_ROWS - indexPath.row]; 
    
    return cell; 
    } 
    

该代码能够访问到标签在使用细胞的存取方法(点表示法用在这里)。代码然后可以设置标签的文本内容。

相关问题