Ios 在tableView单元格上添加子视图会导致严重的修补

Ios 在tableView单元格上添加子视图会导致严重的修补,ios,iphone,swift,uitableview,subview,Ios,Iphone,Swift,Uitableview,Subview,我想在我的iPhone应用程序中为消息的表视图提供聊天功能。 为了执行高质量的渲染,我添加了两个子视图:文本和“容器”,它只是一个带有背景色的视图 即使它第一次工作,当我滚动时,它也会变得非常混乱,因为它一直在添加很多子视图 下面是处理转换的函数,它在滚动时调用 func configChatCell(cell: UITableViewCell, text: String, color:UIColor) { cell.textLabel?.numberOfLines = 0

我想在我的iPhone应用程序中为消息的表视图提供聊天功能。 为了执行高质量的渲染,我添加了两个子视图:文本和“容器”,它只是一个带有背景色的视图

即使它第一次工作,当我滚动时,它也会变得非常混乱,因为它一直在添加很多子视图

下面是处理转换的函数,它在滚动时调用

func configChatCell(cell: UITableViewCell, text: String, color:UIColor)
{
    cell.textLabel?.numberOfLines = 0
    cell.textLabel?.lineBreakMode = NSLineBreakMode.ByWordWrapping
    cell.textLabel?.textColor = UIColor.whiteColor()

    let fixedWidth = cell.bounds.width - 150
    let textView: UITextView = UITextView(frame: CGRect(x: 0, y: 0, width: 10, height: CGFloat.max))
    textView.text = text

    let newSize = textView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.max))
    var newFrame = textView.frame
    newFrame.size = CGSize(width: min(newSize.width, fixedWidth), height: newSize.height)
    textView.sizeThatFits(newFrame.size)
    textView.frame = newFrame
    textView.backgroundColor = UIColor.clearColor()


    self.rowHeight = textView.frame.height+20


    let view = UIView()
    view.backgroundColor = color
    print(textView.frame.height+10)
    view.frame = CGRect(x: 0, y: 5, width: textView.frame.width+50, height: textView.frame.height+10)
    view.layer.cornerRadius = 5


    cell.backgroundColor = UIColor.clearColor()
    cell.contentView.addSubview(view)
    cell.contentView.addSubview(textView)
    cell.contentView.sendSubviewToBack(view)
}
如果每次滚动时删除子视图,则屏幕上不会显示任何内容

有人能帮我找到解决办法吗?还是有其他方法可以做到这一点


提前谢谢

假设您的
configureChatCell
是从
tableView:cellforrowatinexpath:
调用的,那么@Paulw11是正确的;单元格是重复使用的,因此您只能对表中该行进行唯一的更改。在您的示例中,您应该在方法中进行的唯一调用是
textView.text=text
,以及调整
textView
大小以适应的调用。其他所有内容都应该放在故事板中的动态单元原型中,或者,如果您想用代码完成所有事情(我感觉您做得不好),那么将其余配置放在
UITableViewCell
子类中,然后在您的表视图中注册该子类。

假设您的
configureChatCell
是从
tableView:cellforrowatinexpath:
调用的,则@Paulw11是正确的;单元格是重复使用的,因此您只能对表中该行进行唯一的更改。在您的示例中,您应该在方法中进行的唯一调用是
textView.text=text
,以及调整
textView
大小以适应的调用。其他所有内容都应该放在故事板中的动态单元原型中,或者,如果你想用代码完成所有事情(我感觉你做得不好),那么将其余配置放在
UITableViewCell
子类中,然后将该子类注册到表视图中。

我很快就为此编写了一些东西

它以
ChatCell

class ChatCell: UITableViewCell {

    var messageLabel: UILabel? {
        didSet {
            messageLabel?.text = message
        }
    }

    var message: String? {
        didSet {
            messageLabel?.text = message
        }
    }

    class func messageCell(withText text: String, leading: Bool = true) -> ChatCell {
        let cell = ChatCell()
        cell.message = text



        // Make the container
        let container = UIView()
        container.translatesAutoresizingMaskIntoConstraints = false
        cell.contentView.addSubview(container)

        container.topAnchor.constraintEqualToAnchor(cell.contentView.topAnchor, constant: 8).active = true
        container.bottomAnchor.constraintEqualToAnchor(cell.contentView.bottomAnchor, constant: -8).active = true

        if leading {
            container.leadingAnchor.constraintEqualToAnchor(cell.contentView.leadingAnchor, constant: leading ? 8 : 8*8).active = true
            container.trailingAnchor.constraintLessThanOrEqualToAnchor(cell.contentView.trailingAnchor, constant: leading ? -8*8 : -8).active = true
        } else {
            container.leadingAnchor.constraintGreaterThanOrEqualToAnchor(cell.contentView.leadingAnchor, constant: leading ? 8 : 8*8).active = true
            container.trailingAnchor.constraintEqualToAnchor(cell.contentView.trailingAnchor, constant: leading ? -8*8 : -8).active = true
        }

        // Make the messageLabel.
        let messageLabel = UILabel()
        messageLabel.numberOfLines = 0
        messageLabel.textColor = UIColor.whiteColor()
        messageLabel.translatesAutoresizingMaskIntoConstraints = false
        container.addSubview(messageLabel)

        // Add constraints.
        messageLabel.topAnchor.constraintEqualToAnchor(container.topAnchor, constant: 8).active = true
        messageLabel.bottomAnchor.constraintEqualToAnchor(container.bottomAnchor, constant: -8).active = true
        messageLabel.leadingAnchor.constraintEqualToAnchor(container.leadingAnchor, constant: 8).active = true
        messageLabel.trailingAnchor.constraintEqualToAnchor(container.trailingAnchor, constant: -8).active = true

        cell.messageLabel = messageLabel

        container.backgroundColor = UIColor(red:0.19, green:0.70, blue:1.00, alpha:1.00)
        container.layer.cornerRadius = 12.0

        return cell
    }

}
该单元还支持前导和尾随消息以及来回对话。也许可以制作一个元组数组,如下所示:

let messages: [(message: String, leading: Bool)] = [("Hello", true), ("My name is John Doe and this works quite well", false), ("I would agree", true)]
然后在
tableView(tableView:UITableView,cellForRowAtIndexPath:nsindepath)->UITableViewCell
中,可以执行以下操作:

let cell = ChatCell.messageCell(withText: messages[indexPath.row].message, leading: messages[indexPath.row].leading)
return cell

让我知道这是否适合你。我在一个操场上测试了它,它按预期工作

我很快写了一些东西

它以
ChatCell

class ChatCell: UITableViewCell {

    var messageLabel: UILabel? {
        didSet {
            messageLabel?.text = message
        }
    }

    var message: String? {
        didSet {
            messageLabel?.text = message
        }
    }

    class func messageCell(withText text: String, leading: Bool = true) -> ChatCell {
        let cell = ChatCell()
        cell.message = text



        // Make the container
        let container = UIView()
        container.translatesAutoresizingMaskIntoConstraints = false
        cell.contentView.addSubview(container)

        container.topAnchor.constraintEqualToAnchor(cell.contentView.topAnchor, constant: 8).active = true
        container.bottomAnchor.constraintEqualToAnchor(cell.contentView.bottomAnchor, constant: -8).active = true

        if leading {
            container.leadingAnchor.constraintEqualToAnchor(cell.contentView.leadingAnchor, constant: leading ? 8 : 8*8).active = true
            container.trailingAnchor.constraintLessThanOrEqualToAnchor(cell.contentView.trailingAnchor, constant: leading ? -8*8 : -8).active = true
        } else {
            container.leadingAnchor.constraintGreaterThanOrEqualToAnchor(cell.contentView.leadingAnchor, constant: leading ? 8 : 8*8).active = true
            container.trailingAnchor.constraintEqualToAnchor(cell.contentView.trailingAnchor, constant: leading ? -8*8 : -8).active = true
        }

        // Make the messageLabel.
        let messageLabel = UILabel()
        messageLabel.numberOfLines = 0
        messageLabel.textColor = UIColor.whiteColor()
        messageLabel.translatesAutoresizingMaskIntoConstraints = false
        container.addSubview(messageLabel)

        // Add constraints.
        messageLabel.topAnchor.constraintEqualToAnchor(container.topAnchor, constant: 8).active = true
        messageLabel.bottomAnchor.constraintEqualToAnchor(container.bottomAnchor, constant: -8).active = true
        messageLabel.leadingAnchor.constraintEqualToAnchor(container.leadingAnchor, constant: 8).active = true
        messageLabel.trailingAnchor.constraintEqualToAnchor(container.trailingAnchor, constant: -8).active = true

        cell.messageLabel = messageLabel

        container.backgroundColor = UIColor(red:0.19, green:0.70, blue:1.00, alpha:1.00)
        container.layer.cornerRadius = 12.0

        return cell
    }

}
该单元还支持前导和尾随消息以及来回对话。也许可以制作一个元组数组,如下所示:

let messages: [(message: String, leading: Bool)] = [("Hello", true), ("My name is John Doe and this works quite well", false), ("I would agree", true)]
然后在
tableView(tableView:UITableView,cellForRowAtIndexPath:nsindepath)->UITableViewCell
中,可以执行以下操作:

let cell = ChatCell.messageCell(withText: messages[indexPath.row].message, leading: messages[indexPath.row].leading)
return cell

让我知道这是否适合你。我在一个操场上测试了它,它按预期工作

我写了这样的东西。这很简单,但可以阐明解决方案

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("reuseid", forIndexPath: indexPath)

    // Configure the cell...
    let contentView = cell.contentView
    let subviews = contentView.subviews
    for view in subviews {
        if 100 == view.tag {
            let label = view as! UILabel
            label.text = self.datas[indexPath.row]
        } else if 200 == view.tag {
            view.layer.cornerRadius = 10.0
        }
    }

    return cell
}
关键点是配置
tableView(tableView:UITableView,cellForRowAtIndexPath:nsindepath)->UITableViewCell
标记为200的代码中的视图是一个背景视图,具有与标签相同的框架,我在序列图像板中使用布局约束来确保其大小和位置


我写了这样的东西。这很简单,但可以阐明解决方案

override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCellWithIdentifier("reuseid", forIndexPath: indexPath)

    // Configure the cell...
    let contentView = cell.contentView
    let subviews = contentView.subviews
    for view in subviews {
        if 100 == view.tag {
            let label = view as! UILabel
            label.text = self.datas[indexPath.row]
        } else if 200 == view.tag {
            view.layer.cornerRadius = 10.0
        }
    }

    return cell
}
关键点是配置
tableView(tableView:UITableView,cellForRowAtIndexPath:nsindepath)->UITableViewCell
标记为200的代码中的视图是一个背景视图,具有与标签相同的框架,我在序列图像板中使用布局约束来确保其大小和位置


单元格被重复使用,因此您需要多次添加其他视图。如果您创建一个自定义UITableviewCell子类,并使用nib、故事板或单元类中的代码添加视图,则效果会更好。我不认为每次滚动时都需要添加标签和圆角视图。也许它可以在表视图源数据的CellForRowatineXpath中的配置单元格中工作。我将创建一个项目来测试单元格是否重复使用,因此您将多次添加其他视图。如果您创建一个自定义UITableviewCell子类,并使用nib、故事板或单元类中的代码添加视图,则效果会更好。我不认为每次滚动时都需要添加标签和圆角视图。也许它可以在表视图源数据的CellForRowatineXpath中的配置单元格中工作。我将创建一个项目来测试它谢谢!这很有用,我认为这是解决问题的好办法。。然而,在复制代码之后,我仍然有一个问题:在所有单元格上方都有一个白色层,要查看消息,必须单击它(白色层仍然存在,但在消息后面)。此外,只有在返回单元格之前添加container子视图时,container才适合文本。你能再帮我一点忙吗?好的,我解决了白色层,在之前声明的单元格之前是一个冲突。然而,关于textfit的问题仍然存在,但我会努力解决它。真的谢谢你!很高兴听到它基本上起作用了,那么文本拟合到底是怎么回事呢?我不能在评论中添加任何屏幕。。我是新手。文本匹配有一个问题,因为没有换行符,每条消息都会显示在子视图中,并且只占用一行高度。在您的屏幕中,第二条消息有一个换行符,所以我不明白为什么它在我的项目中不起作用。哦,好吧,这是一个简单的修复方法。只需执行此
tableView.estimatedRowHeight=80
和此
tableView.rowHeight=UITableViewAutomaticDimension
。这样,表格视图单元格将根据自动布局自动调整大小。谢谢!这很有用,我认为这是解决问题的好办法。。然而,在复制代码之后,我仍然有一个问题:在所有单元格上都有一个白色层,可以看到