滚动关闭和打开后,视图重新出现在 UITableViewCell 中

Posted

技术标签:

【中文标题】滚动关闭和打开后,视图重新出现在 UITableViewCell 中【英文标题】:View reappears in UITableViewCell after scrolling off and on 【发布时间】:2017-08-04 07:36:04 【问题描述】:

我有一个包含 2 个部分的 UITableView。在第一部分中,我不希望我创建的 UIView 出现在左侧。它在最初加载时工作正常,但当它离开屏幕并重新打开时,它会重新出现。

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)

    let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier") as! ATableCell;
    cell.delegate = self;

    if (indexPath.section == 1)
    
        // let height = cell.bounds.size.height;
        let height = 100;

        let turnsView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: height));
        turnsView.backgroundColor = UIColor.purple;

        cell.addSubview(turnsView);
    
    else
    
        let height = 100;

        let turnsView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: height));
        turnsView.backgroundColor = UIColor.clear;

        cell.addSubview(turnsView);
    

    // Configure the cell...

    cell.backgroundColor = UIColor.clear;
    cell.textLabel?.text = "texting";
    cell.detailTextLabel?.text = "testing";

我不希望紫色视图在任何时候出现在第一部分。

【问题讨论】:

为您的视图分配一个标签,如果它们已经存在于单元格中,则在创建它们之前使用 if-let 语句将它们删除。我有一个类似的问题,当滚动开始时,我的 uilabels 不断重新出现在我的单元格上。 【参考方案1】:

使用时

tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell

您应该使用每个“if”条件及其“else”子句,因为当您滚动关闭它时,它会重用导致它重新出现的单元格。所以如果你不写 else 条件并且如果条件变为 false 它将使用旧的单元格数据。

【讨论】:

【参考方案2】:

始终避免将子视图添加到 cellForRow 中的单元格。您需要了解单元格是重复使用的,并且当您在 cellForRow 中添加 subView 时,不会每次都删除 subView。因此,如果单元格由于滚动打开和关闭而出现 10 次,则会将 10 个子视图添加到重复使用的单元格中。

在你的情况下,同样的事情正在发生。我建议您在 XIB/Prototype 单元格中添加视图。给它一个引用并在 cellForRow 中更改它的 backgroundColor 属性。

或者,如果您不使用 XIB 或原型单元,请在单元类的 init 方法中添加子视图。

var turnsView = UIView()

override init(style: UITableViewCellStyle, reuseIdentifier: String!) 
    super.init(style: style, reuseIdentifier: reuseIdentifier)
    turnsView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: 100)) 
    self.contentView.addSubview(turnsView)


【讨论】:

所以在单元子类的 awakeFromNib 中创建视图。将其设置为标签。然后在 cellForRow 中改变背景颜色?正确的?我希望如此。 在您的单元格中创建一个公共变量 turnView。在 awakeFromNib 中创建并添加它。然后在 cellForRow 中设置其属性,如 turnView.backgroundColor = .purple 如果您使用的是 nib/Storyboard 原型单元,我建议在此处添加视图并提供参考。如果没有,请将其添加到答案中提到的 init 方法中。【参考方案3】:

这应该适合你:

func tableView(_ tableView: UITableView, willDisplay cell: UITableViewCell, forRowAt indexPath: IndexPath)

    let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier") as! ATableCell;
    cell.delegate = self;

    //Remove subviews before adding again
    if let purpleV = cell.viewWithTag(1) 
        purpleV.removeFromSuperview()
    
    if let purpleV = cell.viewWithTag(2) 
        purpleV.removeFromSuperview()
    

    if (indexPath.section == 1)
    
        // let height = cell.bounds.size.height;
        let height = 100;

        let turnsView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: height));
        turnsView.tag = 1
        turnsView.backgroundColor = UIColor.purple;

        cell.addSubview(turnsView);
    
    else
    
        let height = 100;

        let turnsView = UIView(frame: CGRect(x: 0, y: 0, width: 10, height: height));
        turnsView.tag = 2
        turnsView.backgroundColor = UIColor.clear;

        cell.addSubview(turnsView);
    

    // Configure the cell...

    cell.backgroundColor = UIColor.clear;
    cell.textLabel?.text = "texting";
    cell.detailTextLabel?.text = "testing";

阅读 dequeuereusablecell 方法的文档以澄清。

【讨论】:

这可行,但不是一个好的解决方案。在 cellForRow 中添加和删除子视图会在滚动时产生抖动(滚动不会平滑)。永远避免这种情况。 我同意,这不是一个好的解决方案,但我没有遇到任何抽搐,滚动很流畅。【参考方案4】:

这样做会很好:

func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let cell = tableView.dequeueReusableCell(withIdentifier: "reuseIdentifier", for: indexPath)
    // Config the cell...
    if let turnsCell as? ATableCell 
        turnsCell.turnsColor = (indexPath.section == 1 ? UIColor.purple : UIColor.clear)
    

    cell.textLabel?.text = "texting"
    cell.detailTextLabel?.text = "testing"

    return cell


class ATableCell: UITableViewCell 
    var turnsView = UIView()

    var turnsColor: UIColor 
        get 
            return self.turnsView.backgroundColor
        
        set 
            self.turnsView.backgroundColor = newValue
        
    

    override func awakeFromNib() 
        super.awakeFromNib()
        // let height = self.bounds.size.height;
        let height = 100;

        turnsView.frame = CGRect(x: 0, y: 0, width: 10, height: height)
        self.contentView.addSubview(turnsView)
        self.backgroundColor = UIColor.clear
    

【讨论】:

以上是关于滚动关闭和打开后,视图重新出现在 UITableViewCell 中的主要内容,如果未能解决你的问题,请参考以下文章

UIScrollView 在键盘关闭时停止滚动

出现后无法关闭视图控制器

关闭另一个视图后 UITableView 滚动内容大小不正确

无法关闭文本字段上的键盘

SwiftUI 模式表在关闭后重新打开

打开第二个窗口后隐藏主窗口?另外,当第二个窗口被用户关闭时,主窗口如何重新出现?