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

时间:2016-03-27 23:20:57

标签: ios objective-c uitableview

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

MouseListener

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

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

我实现了新属性NSMutableSet self.tagsOfCells,其中我保存了已下载图像的单元格数。 我尝试在TableView方法中进行更改,但效果是相同的:

 -(void)prepareForReuse
{
    [super prepareForReuse];

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

编辑:

我在下载图片时在其中一个方法中填充self.tagsOfCells,这是方法:

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

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

3 个答案:

答案 0 :(得分:3)

与prepare内容相关的操作不应出现在prepareForReuse函数中。

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

  

如果UITableViewCell对象是可重用的 - 也就是说,它具有重用标识符 - 在从UITableView方法dequeueReusableCellWithIdentifier:返回对象之前调用此方法:出于性能原因,您应该仅重置与内容无关的单元格属性,例如,alpha,编辑和选择状态。 tableView:cellForRowAtIndexPath:中的表视图委托应始终在重用单元格时重置所有内容。如果单元对象没有关联的重用标识符,则不会调用此方法。如果重写此方法,则必须确保调用超类实现。

<强>被修改

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异步调用新数据。只是一个建议=)

答案 1 :(得分:1)

我认为这与您使用prepareForReuse无关。几件事看起来很腥。

  1. 您需要先知道自己手机上的delegatecellIndex属性,然后才知道它是否为零。如果它为零则则永远不会设置这些属性。

  2. 我也不认为你需要else条款。它所包含的逻辑与细胞是否可以出列无关。它与配置非零单元有关。

  3. 您问题中缺少的部分是在哪里填充tagsOfCells对象?那段代码很重要。如果您未在cellForRowAtIndexPath中设置标记,则您的数据似乎会不同步,这会导致您的单元格配置错误。

  4. 请尝试以下代码:

    - (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
    {
        static NSString* PlaceholderCellIdentifier = @"Cell";
        CustomTableViewCell *customCell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier forIndexPath:indexPath];
        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];
        }
    
        customCell.delegate = self;
        customCell.cellIndex = indexPath.row;
        customCell.nameOfImage.text = self.names[indexPath.row];
    
        if (indexPath.row % 2 == 0)
        {
            customCell.backgroundColor = [UIColor grayColor];
        }
        else
        {
            customCell.backgroundColor = [UIColor darkGrayColor];
        }
    
        return customCell;
    }
    

    修改

    关于另一个答案中的信息。配置单元格后,未调用prepareForReuse。在您配置单元格之前调用dequeueReusableCell并因此调用时调用它。我不相信prepareForReuse是问题所在。

答案 2 :(得分:0)

看起来您没有使用界面构建器的原型单元格,因此您使用了错误的出列可重用单元格方法。在你的情况下正确的一个没有索引路径参数,例如。

CustomTableViewCell *customCell = [tableView dequeueReusableCellWithIdentifier:PlaceholderCellIdentifier];

正如其他人所说,在你为自定义单元格分配初始化之后你需要移动你的2行初始化,因为它之前没有。例如,您需要将单元格出列,如果没有,则创建一个单元格。然后在您拥有有效实例的情况下在单元格上设置参数。