UITableViewCells中的UIImageViews在缓存的单元格中重新创建

时间:2013-03-01 15:24:11

标签: ios objective-c caching uitableview

我有一个UITableViewCell,我需要随机将插页式图片放入其中。这是有效的,但由于细胞的缓存,图像在桌子下面进一步重复。假设我已经决定将图像放在单元格1,2和25中,这些单元格将有图像,但在单元格1之后,单元格4,8等也可能包含第一个图像。

我猜我需要做的是明确告诉cellForRowAtIndexPath清除缓存并删除任何图像,如果它不符合添加图像的标准。我该怎么做呢?我已经在if语句上尝试了else来做出决定并分配图像。在else中,我尝试将UIImageView的图像设置为nil,但这没有任何区别。

有没有其他方法可以清除缓存,以防止这些图像定期发送到页面上的垃圾邮件?这是我的cellForRowAtIndexPath方法,当前最后一行else中的行对图像没有影响,因此他们(我认为)需要替换有效的内容!

- (UITableViewCell *) tableView: (UITableView *) tableView cellForRowAtIndexPath: (NSIndexPath *) indexPath
{
    // Make and allocate the cell if necessary.
    CustomCell *cell = [tableView dequeueReusableCellWithIdentifier: @"Cell"];
    if (cell == nil) {
        cell = [[CustomCell alloc] initWithStyle: UITableViewCellStyleValue1 reuseIdentifier: @"Cell"];
    }
    cell.lineLabel.text = [[self.fetchedResultsController objectAtIndexPath: indexPath] line];
    cell.actorLabel.text = [[self.fetchedResultsController objectAtIndexPath: indexPath] actor];
    [cell.lineLabel sizeToFitMultipleLines];

    // Get the size each label needs to be when constrained to set width and very long height (8000).
    CGSize labelSize = [cell.lineLabel.text sizeWithFont: cell.lineLabel.font constrainedToSize: CGSizeMake(265, 8000)];

    if ([[cellsToContainInterstitialImages allKeys] containsObject: [thisLine.lineID stringValue]]) {

        UIImageView *interstitialImage = [[UIImageView alloc] init];
        NSNumber *cellTypeNumber = [cellsToContainInterstitialImages valueForKey: [thisLine.lineID stringValue]];
        kInterstitialCellType cellType = [cellTypeNumber intValue];

        if (cellType == kInterstitialCellTypeFirst) {
            interstitialImage = [[UIImageView alloc] initWithImage: [UIImage imageNamed: @"man.png"]];
        }
        else if (cellType == kInterstitialCellTypeSecond) {
            interstitialImage = [[UIImageView alloc] initWithImage: [UIImage imageNamed: @"woman.png"]];
        }
        else {
            interstitialImage = [[UIImageView alloc] initWithImage: [UIImage imageNamed: @"child.png"]];
        }

        [interstitialImage setFrame: CGRectMake(10, cell.lineLabel.frame.size.height + cell.actorLabel.frame.size.height + 10, 150, 150)];
        [cell addSubview: interstitialImage];
    } else {
        UIImageView *interstitialImage = [[UIImageView alloc] init];
        [interstitialImage setImage: nil];
    }

    return cell;
}

3 个答案:

答案 0 :(得分:1)

代码的else分支不会将interstitialImage图像添加到单元格。您应该更改代码以在单元格的构造函数中添加UIImageView,以便在cellForRowAtIndexPath中您必须设置图像,而不是添加子视图。

UIImageView添加到CustomCell,将其设为私有,并为cellForRowAtIndexPath提供使用的属性:

@interface CustomCell : UITableViewCell {
    UIImageView *_interstitialImage;
}
@property (nonatomic,readonly) UIImageView *interstitialImage;
@end

@implementation CustomCell 
-(id)initWithStyle:(UITableViewCellStyle) style reuseIdentifier:(NSString*)reuseId {
    if (self = [super initWithStyle:style reuseIdentifier:reuseId]) {
        _interstitialImage = [[UIImageView alloc] init];
         [_interstitialImage setImage: nil];
         [_interstitialImage setFrame: CGRectMake(10, cell.lineLabel.frame.size.height + cell.actorLabel.frame.size.height + 10, 150, 150)];
         [cell addSubview: _interstitialImage];
    }
    return self;
}
-(UIImageView*)interstitialImage {
    return _interstitialImage;
}
@end

现在,您的cellForRowAtIndexPath将使用cell.interstitialImage,而不是一直分配新的UIImageView。这样可以避免多次添加图像:

if ([[cellsToContainInterstitialImages allKeys] containsObject: [thisLine.lineID stringValue]]) {
    NSNumber *cellTypeNumber = [cellsToContainInterstitialImages valueForKey: [thisLine.lineID stringValue]];
    kInterstitialCellType cellType = [cellTypeNumber intValue];

    if (cellType == kInterstitialCellTypeFirst) {
        [cell.interstitialImage setImage:[UIImage imageNamed: @"man.png"]];
    } else if (cellType == kInterstitialCellTypeSecond) {
        [cell.interstitialImage setImage:[UIImage imageNamed: @"woman.png"]];
    } else {
        [cell.interstitialImage setImage: [UIImage imageNamed: @"child.png"]];
    }
} else {
    [cell.interstitialImage setImage: nil];
}

答案 1 :(得分:0)

最简单的解决方案应该是使用UITableViewDelegate协议的– tableView:willDisplayCell:forRowAtIndexPath:方法。用这种方法清洁细胞。

答案 2 :(得分:0)

问题是在if部分中添加了图像视图。这意味着当重复使用单元格时,您将继续添加越来越多的图像视图。

else部分中,您可以创建虚拟图像视图并将其图像设置为nil。此代码不符合您的意图 - 清除任何现有图像。

您需要做的是确保永远不会向细胞添加第二个图像视图。当您需要清除图像时,您将获得对现有图像视图的引用,而不是创建新图像。