带有 UIImageView 的自定义 UITableViewCell 不为某些单元格加载图像

Posted

技术标签:

【中文标题】带有 UIImageView 的自定义 UITableViewCell 不为某些单元格加载图像【英文标题】:Custom UITableViewCell with a UIImageView not loading image for certain cells 【发布时间】:2013-03-27 16:28:07 【问题描述】:

我有这个非常奇怪的问题。

基本上我有一个 UITableViewCell 子类,我编写了一些插座并将其链接到一个 Nib。

Cell.h 的子类

@property (weak, nonatomic) IBOutlet UIImageView *myImageView;

Cell.m 的子类

@synthesize myImageView = _myImageView; // do i need this?


- (void) setUpCell... image:(UIImage*)image

       if(image)
        self.myImageView.image = image;
    else
        self.myImageView.image = nil;
 

在管理单元格的表格视图的视图控制器中,

我已使用以下代码向 Nib 注册:

[self.tableView registerNib:[UINib nibWithNibName:pathToNibForBaseMenuCell bundle:nil] forCellReuseIdentifier:identifierForBaseMenuCell];

在 cellForRowAtIndexPath 中,我将单元格出列并设置图像...

CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:identifierForBaseMenuCell];

switch (indexPath.section) 


    case 2:
        [cell setUpCell...image:self.cogWheelImageForSettingsIcon];
        break;

    default:
        break;


return cell;

奇怪的是,假设我在第 2 部分中有 10 个单元格(如上),我以相同的方式设置它们,有些单元格显示齿轮图标,而有些则没有!滚动这些单元格进出视图似乎会改变哪些单元格显示图标而哪些不显示。

这意味着注册单元格,包括设置重用标识符,设置nib文件中的子类,所有这些都很好(常见的陷阱)。

在我看来,这种行为模式与内存有关 - 好像某处正在释放某些东西......

这是一张图片来说明我的意思:

请帮忙!

谢谢

Vb

编辑:

为了清楚起见,我还没有对这个表使用任何数据,但尽管如此,我没有理由不应该出现这些齿轮!

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView

return 3;


- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
 
switch (section) 
    case 0:
        return 1;
        break;

    case 1:
        return 10;
        break;

    case 2:
        return 10;
        break;

    default:
        return 0;
        break;



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

CustomCell *cell = [tableView dequeueReusableCellWithIdentifier:identifierForBaseMenuCell];

switch (indexPath.section) 
    case 0:
        [cell setUpCell... text:@"Username" image:nil];
        break;

    case 1:
        [cell setUpCell... text:@"Magazine" image:nil];
        break;

    case 2:
    
        NSString* str = [NSString stringWithFormat:@"Settings: %d",indexPath.row];
        [cell setUpCell... text:str image:self.cogWheelImageForSettingsIcon];
        break;
    

    default:
        break;


return cell;

它的输出是......

我的意思是,如果我为第二部分“设置”中的所有单元格设置相同的图像,为什么只有其中一些单元格显示图像?

自定义单元类:

@interface CustomCell : UITableViewCell
@property (weak, nonatomic) IBOutlet UIImageView *backgroundImageView;
@property (weak, nonatomic) IBOutlet UILabel *mainLabel;
@property (weak, nonatomic) IBOutlet UILabel *arrowView;
@property (weak, nonatomic) IBOutlet UIImageView *myImageView;
- (void) setUpCelltext:(NSString*)text image:(UIImage*)image;


@implementation CustomCell

- (void) setUpCelltext:(NSString*)text image:(UIImage*)image

self.backgroundImageView.image = [UIImage imageNamed:pathForBackgroundImage];
self.myImageView.layer.cornerRadius = kCornerRadiusOfImageView;
self.myImageView.layer.masksToBounds = YES;

if(image)
    self.myImageView.image = image;
else
    self.myImageView.image = nil;

NSDictionary *attrsDictionary = [NSDictionary dictionaryWithObject:self.fontForText forKey:NSFontAttributeName];
NSAttributedString *attrString = [[NSAttributedString alloc] initWithString:text attributes:attrsDictionary];
self.mainLabel.attributedText = attrString;

@end

单元格有自定义字体、箭头视图、背景视图 - 它们都可以正常工作!它们根据部分而变化。它只是不起作用的图像。您可以看到 cellForRowAtIndexPath 调用的此函数将设置图像(如果提供),或者将 imageview 设置为 nil(如果不提供)。

【问题讨论】:

只是对隐藏在代码中的问题的评论,自从最新版本的Objective-C以来,您不再需要@synthesize了。它将使用“_”约定自动完成 谢谢,我删除了! 看起来您在 UITableView 数据源中每次都在传递 self.cogWheelImageForSettingsIcon,所以我不明白您怎么可能不让每个单元格都带有图标图像. 这真是令人费解! 两点:一 - 使用@reply 通知您要回复的人,以便我可以更好地帮助您。二 - 我建议只用代码编写它。没有太多好处,而且还有很多额外的并发症。 【参考方案1】:

原来问题与在我的笔尖中使用“imageView”作为我的 imageView 的名称有关。这后来被改变了,但原来的关系是 UITableViewCell 的实例变量而不是自定义单元格。

故事的寓意:不要将自定义表格视图单元格的图像视图称为“imageView”!

【讨论】:

我遇到了完全相同的问题。在使用正确的子类名称命名 TableViewCell 类属性后,确保在情节提要上设置了关系解决了我的问题。附言。当我确定那部分一切正常时,我注意到代码中有空的 IBOutlet 关系。【参考方案2】:

UITableViewCells 使用 dequeueReusableCellWithIdentifier: 从旧单元格中重绘。如果您不希望重复使用单元格,则需要每次在 tableView:cellForRowAtIndexPath: 函数中初始化一个新单元格。

但是,如果您想重复使用单元格(推荐),那么您应该每次在 tableView:cellForRowAtIndexPath: 内调用您的 - (void) setUpCell... image:(UIImage*)image 函数,以确保图像仅设置为正确的单元格。

您似乎也在使用存储在您的 UITableViewCell 子类中的数据,但是当该单元格在不同的行上重复使用时,它仍然会认为它与原始行中的单元格相同。

例如:在第 2 行创建了一个单元格,并具有一个图标图像。单元格 2 已离开屏幕,现在正用于第 16 行。第 16 行不应有图像,但该单元格仍认为它与第 2 行中的单元格相同,并继续显示其图像。

如果您希望重复使用每个单元格并为每个单元格设置唯一数据,请仅使用外部数据集(例如:NSArray),该数据集提供绘制单元格所需的信息并传递该信息每次都添加到单元格,而不是依赖于您在创建单元格时提供的信息。

【讨论】:

但这正是我正在做的。最后一段代码来自我的 cellForRowAtIndexPath。即将进入第二部分的每个单元格都调用了 setUpCell。 @Vazzyb 哦。你做错了。您需要从数据集中提取。您正在从单元格的数据中提取数据。该单元格可以由任何行创建和重用,因此您需要一个使用 indexPath.row 属性引用的外部数据集 @Vazzyb 请阅读我的编辑。如果您想要一个示例,请发布您的子类和完整的tableView:cellForRowAtIndexPath: 代码。 我添加了我的代码和所发生情况的屏幕截图。我的理解是,对于屏幕上的每个位置,UIKit 都会调用 celLForRowAtIndexPath。 UITableViewCell 对象然后交给你,所以你不需要创建一个新的(回收)。然后,您将该单元格设置为就好像它是新的一样。我将它设置为新的,因为 setUpCell 检查图像是否为 nil,如果是,它也将 imageView 的图像设置为 nil。 @Vazzyb 你能发布整个 UITableViewCell 子类吗?您似乎在其中存储了不应该存储的信息。

以上是关于带有 UIImageView 的自定义 UITableViewCell 不为某些单元格加载图像的主要内容,如果未能解决你的问题,请参考以下文章

在 xib 中带有可选 UIImageView 的自定义 UITableViewCell

UIImageView 在具有不同高度的自定义 UITableViewCell 内自动调整大小

带有在代码中绘制的自定义图像的 UITableViewCell

在自定义UITableViewCell中保持UIImageView的宽高比

带有 UIProgressView 的自定义 UICollectionViewCell 在重用单元格上显示 progressView

设置 UIImageView 的高度时 AutoLayout 失败