滚动时 UITableViewCell 的奇怪行为,UIButtons 消失

Posted

技术标签:

【中文标题】滚动时 UITableViewCell 的奇怪行为,UIButtons 消失【英文标题】:Odd behaviour with UITableViewCell when scrolling, UIButtons disappearing 【发布时间】:2015-02-11 10:54:07 【问题描述】:

我正在尝试在我的自定义 UITableViewCell 中设置一些 UIButton 和 UILabel。对于表中的每一行,我有 4 个带有用户个人资料图像的按钮,每个按钮下方是一个显示用户名的标签。图片和用户名取自 Parse.com。我有一个大小为 34 的朋友数组,我显示 9 行,所以最后两个按钮和标签必须隐藏。下面的代码有效,但由于某种原因,当我向上滚动表格时,其他一些行也会隐藏它们最右边的两个按钮和标签。我想知道我从数组加载图像的逻辑是否不正确。不知道这里发生了什么。任何建议将不胜感激。

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

    FriendViewCell *cell = (FriendViewCell *)[tableView dequeueReusableCellWithIdentifier:@"friendCell" forIndexPath:indexPath];

    for (int i = 0; i < 4; i++) 
        if ((int)indexPath.row * 4 + i < [self.currentUser.friends count]) 
            UIButton *button = cell.buttons[i];

            [button setTag:(int)indexPath.row * 4 + i];
            button.layer.cornerRadius = button.frame.size.width / 2;
            button.clipsToBounds = YES;
            UILabel *label = cell.labels[i];
            [button addTarget:self action:@selector(friendTapped:) forControlEvents:UIControlEventTouchUpInside];

            //here we need to decide what to access
            PFUser *user = self.currentUser.friends[(int)indexPath.row * 4 + i];
            label.text = user.username;
            PFFile *userImageFile = user[@"profilePic"];
            [userImageFile getDataInBackgroundWithBlock: ^(NSData *imageData, NSError *error) 
                if (!error) 
                    UIImage *image = [UIImage imageWithData:imageData];
                    [button setBackgroundImage:image forState:UIControlStateNormal];
                
            ];
        
        else 
            UIButton *button = cell.buttons[i];
            [button setEnabled:NO];
            [button setHidden:YES];
            UILabel *label = cell.labels[i];
            [label setHidden:YES];
        
    
    return cell;

【问题讨论】:

@Yuvrajsinh 答案应该可以解决您的大部分问题。很多人忽略的一点是,在表格视图中,单元格被重用。因此,如果不再更改,您更改的任何内容都将保留。几乎总是在 if else 中做相反的事情是一件简单的事情。 为什么我想隐藏的按钮会出现这种情况?如果单元格被重复使用,那么某些个人资料图片不会也被重复使用,因此您最终会让用户拥有相同的个人资料图片吗? 没错。如果您在 else 中关闭隐藏逻辑,您会注意到配置文件图像正在被重复使用,但是因为当您决定取消隐藏它们时,您会设置您没有注意到的图像。此外,您可能需要考虑将图像设置为占位符图像,因为您的 getDataInBackgroundWithBlock: 可能需要一段时间,并且您不想看到旧图像也希望将图像设置在主线程上。不过,这完全是题外话。很高兴它现在对你有用。 哦,我明白了,单元创建行要么创建一个新单元,要么在重用队列中重用一个。如果你得到一个新的单元格,那么一切都会好起来的,但如果它是一个可重复使用的单元格,我们将取回同一个单元格。我一直在更改个人资料图片和用户名,所以这很好,但是如果该单元格返回隐藏按钮,除非我先取消隐藏,否则它仍然会被隐藏。知道了。我想知道慢速图像会发生什么,只是对其进行了测试,它在等待新图像的同时使用旧图像。创建单元格后,我将设置占位符图像。谢谢! 【参考方案1】:

您可以尝试在您的第一次传导中取消隐藏按钮和标签,例如:

if ((int)indexPath.row * 4 + i < [self.currentUser.friends count]) 
     [button setEnabled:YES];
     [button setHidden:NO];
     [label setHidden:NO];
     // Other code

else
......

【讨论】:

【参考方案2】:

处理此问题的“ios”方法是填写自定义单元格的 prepareForReuse 方法。这是您应该重置缓存系统可能重用的单元格的各种属性的地方。

Apple Docs

-prepareForReuse

准备一个可重用的单元格以供表格视图的委托重用。

讨论

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

【讨论】:

以上是关于滚动时 UITableViewCell 的奇怪行为,UIButtons 消失的主要内容,如果未能解决你的问题,请参考以下文章

UITableViewCell 内的 UICollectionView 滚动行为

UITableviewCell 高度未在滚动时重置

UITableView 奇怪的行为

Tableview单元格内UItextView的奇怪行为

UITableViewCell 和 UITextView 之间的 UIMenuController 奇怪行为

浮动操作按钮滚动奇怪的行为