UITableviewCell 在我滚动时显示另一个单元格的文本

Posted

技术标签:

【中文标题】UITableviewCell 在我滚动时显示另一个单元格的文本【英文标题】:UITableviewCell display text for another cell when I scroll 【发布时间】:2014-09-23 15:05:44 【问题描述】:

当我滚动自定义 UITableviewCells 时,得到错误的内容(另一个单元格的文本)。这是随机发生的。我尝试清除单元格,但后来我得到了一些空白单元格。我的代码如下。谁能告诉我发生了什么。我从这里和其他地方阅读了许多需要清除单元格的文章,但没有一个对我有用,因为我不确定您在什么时候清除数据。我什至尝试在我的单元格的班级中实现 prepareForReuse 但没有好处。

- (UITableViewCell *)tableView:(UITableView *)theTableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    if ([self.products count] == 0) 
        UITableViewCell *cell = [[UITableViewCell alloc] init];
        return cell;
    

    static NSString *CellIdentifier = @"AvailableCustomerProductCell";

    AvailableCustomerProductTableViewCell *cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
    cell.accessoryType = UITableViewCellAccessoryNone;

    cell.buttonAdd.tag = indexPath.row;
    [cell.buttonAdd addTarget: self action: @selector(addToSelectedProduct:) forControlEvents: UIControlEventTouchUpInside];

    Product *prod = nil;
    if (theTableView == self.searchDisplayController.searchResultsTableView) 
        prod = (Product *)[self.filteredProducts objectAtIndex:indexPath.row];
     else 
        prod = (Product *)[self.products objectAtIndex:indexPath.row];
    

    if (prod != nil) 
        cell.pNumber.text = prod.number;
        cell.description.text = prod.desc;

        if ([Common getProductPromotion:prod] != nil)  
            cell.btnPromotionTag.hidden = NO;
            cell.btnPromotionTag.tag = indexPath.row;
            [cell.btnPromotionTag addTarget: self action: @selector(showPromotionDetails:) forControlEvents: UIControlEventTouchUpInside];
        
        else
            cell.btnPromotionTag.hidden = YES;
        

        //Get the customer product price, first:
        //If if the product has a record in the productCustomerPrices list
        //if not get the price from the standard price.

        if (self.order.orderOrderCustomer != nil) 
            CustomerPrice *custPrice = [Common getPriceForCustomer:self.order.customerRef forProduct:prod.productId];

            if (custPrice != nil) 
                //get the customer price
                [cell.btnPrice setTitle:[Common getCurrencyFormattedStringFromFloat:[custPrice.price floatValue]] forState:UIControlStateNormal];
                [cell.btnPrice setTitleColor:[UIColor colorWithRed:0.01 green:0.65 blue:0.77 alpha:1] forState:UIControlStateNormal];
                cell.btnPrice.enabled = NO;
            else
                //get the standard price
                float price =[[Common  GetProductStandardPrice:prod.productStanddardPrices ByQuantity:[NSNumber numberWithInt:1]] floatValue];
                [cell.btnPrice setTitle: [Common getCurrencyFormattedStringFromFloat:price] forState:UIControlStateNormal ];
                [cell.btnPrice setTitleColor:[UIColor colorWithRed:1.0 green:0.39 blue:0.0 alpha:1] forState:UIControlStateNormal];
                cell.btnPrice.tag = indexPath.row;
                [cell.btnPrice addTarget: self action: @selector(showStandardPrices:) forControlEvents: UIControlEventTouchUpInside];
                cell.btnPrice.enabled = YES;
            
        
    

    UISwipeGestureRecognizer* sgr = [[UISwipeGestureRecognizer alloc] initWithTarget:self action:@selector(cellSwiped:)];
    [sgr setDirection:UISwipeGestureRecognizerDirectionRight];
    [cell addGestureRecognizer:sgr];

    return cell;

【问题讨论】:

哪个对象的文本没有消失? 顺便说一句,您应该在单元格子类中而不是在 cellForRow 中添加手势识别器 目标方法在视图控制器上。据我所知,从牢房中调用它太麻烦了 您的手势识别器可以多次添加到单个单元格上 你是对的。没想到。会改的。 【参考方案1】:

您的问题几乎可以肯定与表格视图回收单元格这一事实有关。正如您所说,这就是需要“清除”单元格的原因。

例如,如果您有一个靠近顶部的单元格显示了一张图片,如果您进一步向下滚动并且同一单元格用于显示不应有图片的单元格,则该图片仍会出现,除非从那以后你已经删除了它。即使您有 100 个要显示的单元格,实际存在的实例也可能只有少数——它们会被回收。

话虽如此,即使您没有说仍然出现哪个文本,如果prodnil,它可能是各种对象,包括pNumberdescription。如果self.order.orderOrderCustomernil,也是如此。为了避免这样的事情,您可以在获得cell 后立即输入以下内容:

cell.pNumber.tex = @"";
cell.description.text = @"";
//etc

另一个注意事项:您正在将目标添加到单元格的 buttonAdd 按钮。您应该删除它之前的行上的现有操作。例如:

[cell.buttonAdd removeTarget:nil action:NULL forControlEvents:UIControlEventAllEvents];
[cell.buttonAdd addTarget: self action: @selector(addToSelectedProduct:) forControlEvents: UIControlEventTouchUpInside];

btnPromotionTagbtnPrice 也是如此。

【讨论】:

我试过 [cell.btnPrice setTitle:@"" forState:UIControlStateNormal];单元格出列后立即不起作用。 到底是什么问题?什么文字仍然出现?是cell.btnPrice 还是其他? cell.btnPrice 显示用于另一个单元格的文本。例如,我知道产品 A 在 10 号单元格上。我看到 btnPrice 标题为 10.25,然后我将单元格 10 滚动出视图,然后将其滚动回视图和 Kaboom 它显示 23.45 或其他单元格的任何价格,但有时它仍然正确我需要滚动出视图几个在我在那个单元格上看到错误价格之前的时间 self.order.customerRef 有变化吗?调查一下。因为custPrice 依赖于此。 self.order.customerRef 在用户选择不同的客户时会发生变化,但是当发生这种情况时,我会清除产品和价格并重新加载整个表格。我所有的测试都是针对 1 位客户的,所以这不是问题【参考方案2】:

确保在每次cellForRowAtIndexPath 调用中都会重置单元格的状态。您有一堆 if/else 条件,并且控制流使得用于在单元格上设置内容的代码根本不会被调用,这就是保留先前重用单元格的内容的原因。

我的规则是始终为ifs 匹配其他条件,在此我更改单元格的状态(如果没有,则至少为空白)。如果是UITableViewCell 子类,您可以在prepareForReuse 中重置状态

【讨论】:

我评论了两个 if - 不是真的需要,他们总是 eval 为 true 删除 if if (prod != nil) 和后仍然出现问题 if (self.order.orderOrderCustomer != nil) 但是,这一行 CustomerPrice *custPrice = [Common getPriceForCustomer:self.order.customerRef forProduct:prod.productId]; 可能需要几毫秒,我怀疑是延迟导致了问题而不是重用。我添加了 [cell.btnPrice setTitle:@"" forState:UIControlStateNormal];在单元格出队之后,没有任何区别 并为支离破碎的 cmets 道歉。每次我按回车时都会发帖。我总是忘记换档输入【参考方案3】:

通常,如果有数百条记录,最好对所有单元格使用相同的标识符,以便单元格可以重用内存。否则,如果 Tableview 足够长并且用户快速滚动浏览它,会导致大量的 allocs/deallocs,从而导致滚动不流畅。然后总是将行特定代码放在检查单元格为 nil 的条件之外。

看看这段代码sn-p:

-(UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath 
    NSString *cellIdentifier = @"MY_CELL_IDENTIFIER";
    UITableViewCell *cell = [tableView dequeueReusableCellWithIdentifier:cellIdentifier];
    if (cell == nil) 
        cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleSubtitle reuseIdentifier:cellIdentifier];
        // Everything that is similar in all the cells should be defined here
        // like frames, background colors, label colors, indentation etc.
    
    // everything that is row specific should go here
    // like image, label text, progress view progress etc.
    return cell;

【讨论】:

我对所有单元格使用相同的标识符。零细胞?我正在查。我正在使用情节提要,原型单元在那里定义。据我所知,dequeueReusableCellWithIdentifier 保证不会在该设置中返回 nil

以上是关于UITableviewCell 在我滚动时显示另一个单元格的文本的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCells 笔尖在我滚动时显示默认值

ios - UITableViewCell 滚动时显示错误数据

自定义 UITableViewCell 在滚动时显示完整单元格之前不显示数据

悬停时显示另一个 div

UITableviewCell在ios中滚动时显示不正确

用户登录 Facebook SDK 时显示另一个视图