3

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

在我的cellForRowAtIndexPath方法中,根据返回的数据类型,我正在为我的单元格设置样式。如果数据是“月”标题,则它是一个细长的单元格,如果它是“新闻项目”,它将是一个更大的白色单元格。

在此处输入图像描述

当表格加载时,一切看起来都很好,但是如果我向下滚动以创建更多单元格然后向上滚动,单元格将被重新创建,最终滚动速度变慢,因为我的内存不足。

当我设置断点时,dequeueReusableCellWithIdentifier总是返回 nil,所以我的单元格永远不会被重复使用,这似乎是一个问题。

在这张图片中,您可以看到单元格彼此堆叠并弄乱了:

在此处输入图像描述

这是我的代码:

- (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;

}

感谢您的任何帮助或建议!

4

4 回答 4

2

当您使用没有动态原型的情节提要时,您需要将创建和添加子视图的代码放在if (cell==nil)块内。否则,每次重新使用 tableview 单元格时,都会再次添加所有子视图。

展望未来,我的建议是使用带有动态原型(带有子类 UITableViewCells)的 Storyboard,并在 IB 的单元格中进行自定义。

于 2013-02-28T00:26:48.033 回答
1

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

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

使用动态原型单元,对于原型单元,不需要单元分配和检查正确的单元标识符。

在情节提要上创建两个原型单元格并为它们提供不同的单元格标识符,在您的情况下为 NewsCellIdentifer 和 MonthCellIdentifier。确保 NewsCellIdentifer 的拼写,因为您错过i了 NewsCellIdentifer。

于 2013-02-27T16:57:21.013 回答
1

有趣的问题。你说你的细胞出队返回为零。这是否已通过断点或日志确认?或者这仅仅是从您发布的图像中扣除的?

在我看来,可能还有另一个罪魁祸首是电池相互堆叠而不被重复使用的问题。

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

另外,如果我可以对您代码的其他方面提出建议。您对标题进行了自定义编码,并且没有使用实际的部分标题。这对我来说太奇怪了。此外,您还有一个多余的“if (item.isMonth)”。由于一个已经在另一个的块中,它总是一个月份的项目。

于 2013-02-27T17:32:38.597 回答
0

我在 iOS 7 和情节提要上遇到了同样的问题,而在旧 Xcode-SDK 版本上使用相同的代码我从来没有遇到过这个问题,并且尝试了很多来自 stackoverflow 的建议,我无法修复它,你猜怎么着?!Apple 的TableView Programming Guide有详细解释的指南。甚至没有必要使用cell==nil.

因此,我将说明放在这里,希望对其他人有所帮助:

要使用可以正确重用的故事板创建自定义 tableview 单元格,您可以采用两种不同的方法。我个人更喜欢第一个更直接的解决方案,但我将两种解决方案都放在这里。

第一种方法

  1. 使用 Master-Detail Application 模板创建一个项目并选择 Use Storyboards 选项。
  2. 在故事板画布上,选择主视图控制器。
  3. 在身份检查器中,验证 Class 是否设置为自定义 MasterViewController 类。
  4. 选择主视图控制器内的表视图。
  5. 在属性检查器中,确认内容弹出菜单设置为动态原型。
  6. 选择原型单元格。
  7. 在“属性”检查器中,在“样式”弹出式菜单中选择“自定义”。
  8. 在标识符文本字段中输入重用标识符。这与您在消息中发送到表视图的重用标识符相同dequeueReusableCellWithIdentifier:
  9. 在“附件”弹出菜单中选择“披露指示器”。
  10. 将对象从库中拖到单元格上。在此示例中,拖动两个标签对象并将它们放置在单元格末端附近(为附件视图留出空间)。
  11. 选择对象并设置它们的属性、大小和自动调整大小特征。

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

现在编写您通常编写的代码来获取表视图的数据。(对于本例,您需要的唯一数据是每个单元格的行号。)实现数据源方法 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

    @property (nonatomic, weak) IBOutlet UILabel *firstLabel; @property(非原子,弱)IBOutlet UILabel *secondLabel; @结尾

  3. 将以下代码添加到中的实现中MyTableViewCell.m

    @synthesize 第一个标签,第二个标签;

  4. 将以下代码行添加到实现数据源的源文件中:

    #import "MyTableViewCell.h"

  5. 使用 将Identity inspector原型单元的 Class 设置为MyTableViewCell

  6. 使用 Connections 检查器将原型单元中的两个出口连接到它们相应的标签。 在此处输入图像描述

  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;
    }
    

代码使用访问器方法访问单元格中的标签(此处使用点表示法)。然后代码可以设置标签的文本内容。

于 2013-11-19T18:55:58.843 回答