ios - prepareForReuse 之后的 UITableView - Cell 中的所有数据都消失了

标签 ios objective-c uitableview

我有一个带有 customCell 的 TableView,它具有以下属性:

@interface CustomTableViewCell : UITableViewCell

@property (weak, nonatomic) IBOutlet UIImageView *image;
@property (weak, nonatomic) IBOutlet UILabel *nameOfImage;
@property (weak, nonatomic) IBOutlet UIButton *start;
@property (weak, nonatomic) IBOutlet UIButton *stop;
@property (weak, nonatomic) IBOutlet UIProgressView *progressView;
@property (weak, nonatomic) IBOutlet UILabel *realProgressStatus;

在表格 View 中 - 当用户按下开始按钮时 - 下载图像,以及带有 realProgressStatus 的 progressView 反射(reflect)当前情况。在这个阶段一切都很完美,但是当滚动表格 View 并返回到单元格时 - 已经用数据完成了 - 所有信息都消失了(除了 nameOfImage,我单独设置了它)。
我在 CustomTableViewCell 类中实现了下一个方法:
 -(void)prepareForReuse
{
    [super prepareForReuse];

    self.progressView.progress = 0.1;
    self.realProgressStatus.text = @"";
    self.image.image = [UIImage imageNamed:@"placeholder"];
}

我实现了新属性 NSMutableSet self.tagsOfCells,我在其中保存了已下载图像的单元格数量。
我试图在 TableView 方法中进行更改,但效果是一样的:
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    static NSString* PlaceholderCellIdentifier = @"Cell";
    CustomTableViewCell *customCell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier forIndexPath:indexPath];
    customCell.delegate = self;
    customCell.cellIndex = indexPath.row;
    if (!customCell)
    {
        customCell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                                reuseIdentifier:@"cell"];
    }
    else
    {
           NSNumber *myNum = [NSNumber numberWithInteger:indexPath.row];

        if (![self.tagsOfCells containsObject:myNum])
        {
            NSLog(@"Row: %ld",(long)indexPath.row);
            UIImage *img = [UIImage imageNamed:@"placeholder"];
            customCell.realProgressStatus.text = @"";
            customCell.progressView.progress = 0.1;
            customCell.image.image = img;
            [customCell setNeedsLayout];
        }
    }

    if ( indexPath.row % 2 == 0 )
        customCell.backgroundColor = [UIColor grayColor];
    else
        customCell.backgroundColor = [UIColor darkGrayColor];

    customCell.nameOfImage.text = self.names[indexPath.row];
    return customCell;
}

编辑:

我在下载图像期间以一种方法填充 self.tagsOfCells,方法如下:
-(void)connectionDidFinishLoading:(NSURLConnection *)connection
{
    self.customCell.realProgressStatus.text = @"Downloaded";

    UIImage *img = [UIImage imageWithData:self.imageData];
    self.customCell.image.image = img;
    self.customCell.tag = self.selectedCell;
    [self.savedImages setObject:img forKey:self.customCell.nameOfImage.text];
    NSNumber *myNum = [NSNumber numberWithInteger:self.selectedCell];
    [self.tagsOfCells addObject:myNum];

}

提前感谢您的任何帮助或建议。

最佳答案

不应在 prepareForReuse 函数中发生与内容相关的操作。

https://developer.apple.com/library/ios/documentation/UIKit/Reference/UITableViewCell_Class/#//apple_ref/occ/instm/UITableViewCell/prepareForReuse

If a UITableViewCell object is reusable—that is, it has a reuse identifier—this method is invoked just before the object is returned from the UITableView method dequeueReusableCellWithIdentifier:. For performance reasons, you should only reset attributes of the cell that are not related to content, for example, alpha, editing, and selection state. The table view's delegate in tableView:cellForRowAtIndexPath: should always reset all content when reusing a cell. If the cell object does not have an associated reuse identifier, this method is not called. If you override this method, you must be sure to invoke the superclass implementation.



已编辑

Alfie 是对的,从 cellForRowAtIndexPath 返回后没有调用 prepareForReuse

我会尝试的第一件事是编辑代码
if (!customCell)
{
    customCell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                            reuseIdentifier:@"cell"];
}
else
{
       NSNumber *myNum = [NSNumber numberWithInteger:indexPath.row];

    if (![self.tagsOfCells containsObject:myNum])
    {
        NSLog(@"Row: %ld",(long)indexPath.row);
        UIImage *img = [UIImage imageNamed:@"placeholder"];
        customCell.realProgressStatus.text = @"";
        customCell.progressView.progress = 0.1;
        customCell.image.image = img;
        [customCell setNeedsLayout];
    }
}

到以下
if (!customCell)
{
    customCell = [[CustomTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault
                                            reuseIdentifier:@"cell"];
}

NSNumber *myNum = [NSNumber numberWithInteger:indexPath.row];

if (![self.tagsOfCells containsObject:myNum])
{
    NSLog(@"Row: %ld",(long)indexPath.row);
    UIImage *img = [UIImage imageNamed:@"placeholder"];
    customCell.realProgressStatus.text = @"";
    customCell.progressView.progress = 0.1;
    customCell.image.image = img;
    [customCell setNeedsLayout];
}

这确实不是一项昂贵的操作,最好将这个逻辑放在一个地方。特别是因为你摆脱了 prepareForReuse,这应该改变。

当你滚动出去,然后回来找不到你的数据的原因是cellForRowAtIndexPath再次被调用,这会导致默认数据覆盖您刚刚添加的新数据。

您可能希望拥有一个底层数据结构并从那里检索数据。

我会做什么:

例如,您可以保留一个可变列表
NSMutableArray* tableData = [[NSMutableArray alloc] init];

将每一行的图像数据添加到数组中
[tableData add:imageData];

然后显示它添加cellForRowAtIndexPath
customCell.image.image = [tableData objectAtIndex:[indexPath row]];

这将是用数据填充 UITableView 的正常做法。这样,即使您滚动离开 tableData 也会保持不变,从而产生一致的数据。

备注

我还将使用 NSURLSession 异步调用新数据来自 内如果我必须实现这个单元格。只是一个建议=)

关于ios - prepareForReuse 之后的 UITableView - Cell 中的所有数据都消失了,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/36253836/

相关文章:

ios - iOS 中 NSURLConnection 的间歇性 SSL 错误

iphone - 如何将相框添加到 UIImage?

swift - 来自 Firebase 的图像未显示在 TableView 单元格中 [Swift]

ios - Xcode 和 ios - Storyboard对于动态生成的菜单和内容来说是一个好主意吗?

ios - 来自 UIWebview 的文件上传错误

ios - 使用 Parse.com 进行多查询搜索

iOS Swift - 自定义 UITableViewCell

ios - 在 Swift 中使用 RestKit 和 CoreData

ios - 我正在学习 iOS 中的 "Audio File Stream Services Reference"

ios - 对静态单元格使用 UITableViewAutomaticDimension 后,单元格高度太小