swift - UICollectionViewCell 未正确重用

标签 swift uicollectionview uicollectionviewcell

我正在这个应用程序中构建聊天功能,但我遇到了一些奇怪的事情。我认为 UICollectionViewCells 没有被正确重用。当您发送新消息或快速滚动时,您会看到“气泡”未正确显示,但如果您来回滚动,它们就会恢复正常,这里有 2 个实际外观的屏幕截图:

enter image description here

enter image description here

class CurrentUserMessageLogCVCell: UICollectionViewCell {

let messageTextView: UITextView = {
    let textView = UITextView()
    textView.isSelectable = false
    textView.isEditable = false
    return textView
}()

let bubbleView: UIView = {
    let view = UIView()
    return view
}()

let bubbleImageView: UIImageView = {
    let imageView = UIImageView()
    imageView.translatesAutoresizingMaskIntoConstraints = false
    return imageView
}()

override init(frame: CGRect) {
    super.init(frame: frame)
    addSubview(bubbleView)
    addSubview(messageTextView)
    bubbleView.addSubview(bubbleImageView)
    bubbleImageView.topAnchor.constraint(equalTo: bubbleView.topAnchor).isActive = true
    bubbleImageView.bottomAnchor.constraint(equalTo: bubbleView.bottomAnchor).isActive = true
    bubbleImageView.leadingAnchor.constraint(equalTo: bubbleView.leadingAnchor, constant: 8).isActive = true
    bubbleImageView.trailingAnchor.constraint(equalTo: bubbleView.trailingAnchor, constant: -8).isActive = true

}

override func prepareForReuse() {
    super.prepareForReuse()
    applyTheme()
    updateView()
    messageTextView.text = ""
    bubbleImageView.image = UIImage(named: "")
}

var message: Message? {
    didSet {
        updateView()
    }
}

func updateView() {
    if let text = message?.text {
        incomingOrOutgoingMessageWithCalculatedFrame(text: text)
        messageTextView.text = text
    }
}

func incomingOrOutgoingMessageWithCalculatedFrame(text: String) {
    let size = CGSize(width: 0.66 * contentView.frame.width, height: .infinity)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    let estimatedFrame = NSString(string: text).boundingRect(with: size,
                                                             options: options,
                                                             attributes:[NSAttributedStringKey.font: UIFont(name: Fonts.OpenSans_Regular, size: 13)!],
                                                             context: nil)

    if message?.fromId == Api.Users.CURRENT_USER?.uid {
        // outgoing message
        bubbleImageView.image = UIImage(named: "chat_bubble_outgoing")!.resizableImage(withCapInsets: UIEdgeInsets(top: 17, left: 21, bottom: 17, right: 21)).withRenderingMode(.alwaysTemplate)
        bubbleImageView.tintColor = Theme.current.view_messageBubbleView_outgoing_backgroundColor
        messageTextView.textColor = Theme.current.textView_messageBubble_incoming_textColor

        bubbleView.frame = CGRect(x: contentView.frame.width - estimatedFrame.width - 50,
                                 y: 0,
                                 width: estimatedFrame.width + 50,
                                 height: estimatedFrame.height + 20)

        messageTextView.frame = CGRect(x: contentView.frame.width - estimatedFrame.width - 32,
                                     y: 0,
                                     width: estimatedFrame.width + 10,
                                     height: estimatedFrame.height + 20)
    }
    else {
        // incoming message
        bubbleImageView.tintColor = Theme.current.view_messageBubbleView_incoming_backgroundColor
        messageTextView.textColor = Theme.current.textView_messageBubble_outgoing_textColor
        bubbleImageView.image = UIImage(named: "chat_bubble_incoming")!.resizableImage(withCapInsets: UIEdgeInsets(top: 17, left: 21, bottom: 17, right: 21)).withRenderingMode(.alwaysTemplate)
        bubbleView.frame = CGRect(x: 0, y: 0, width: estimatedFrame.width + 50, height: estimatedFrame.height + 20)
        messageTextView.frame = CGRect(x: 20, y: 0, width: estimatedFrame.width + 20, height: estimatedFrame.height + 20)
    } 
  }
 }

    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    return messages.count
}

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: messageCellId, for: indexPath) as! CurrentUserMessageLogCVCell
    let message = messages[indexPath.row]
    cell.message = message
    return cell
}

func registerCells() {
    collectionView.register(CurrentUserMessageLogCVCell.self, forCellWithReuseIdentifier: messageCellId)

}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
    if let messageText = messages[indexPath.row].text {
        let estimatedFrame = estimateFrameForText(text: messageText)
        return CGSize(width: view.frame.width, height: estimatedFrame.height)
    }
    return CGSize(width: view.frame.width, height: 100)
}

private func estimateFrameForText(text: String) -> CGSize {
    let size = CGSize(width: 0.66 * view.frame.width, height: .infinity)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    let estimatedFrame = NSString(string: text).boundingRect(with: size,
                                                           options: options,
                                                           attributes:[NSAttributedStringKey.font: UIFont(name: Fonts.OpenSans_Regular, size: 13)!],
                                                                    context: nil)
    return CGSize(width: view.frame.width, height: estimatedFrame.height + 20)
}

知道是什么原因造成的以及如何解决这种奇怪的行为吗?

最佳答案

根据 @Ladislav 的建议,我已将单元格分为 2 个,一个用于传入消息,一个用于传出消息。这对解决问题没有帮助,但它帮助我发现实际问题出在 applyTheme() 函数中,更准确地说,是设置 messageTextView.backgroundColor = 。清晰这弄乱了整个气泡图像。我所要做的就是在常量声明中移动该行,这最终解决了问题。

关于swift - UICollectionViewCell 未正确重用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/52145097/

相关文章:

ios - Swift PNG 图像以不正确的方向保存

swift - --> (dash dash greater than) 运算符在 Swift 中是什么意思

Swift:未调用自定义 UINavigationController

ios - UICollectionViewCell 计数总是返回 0

swift - 如何在一个tableview中使用两个collectionview

swift - JSQMessageViewController 打开时崩溃

ios - 从 collectionView 返回什么(_ :viewForSupplementaryElementOfKind:at:) when you want to return nothing?

swift - tableView 或 collectionview dequeue 可重复使用如何快速工作

ios - 以相反的顺序填充 UICollectionView

ios - UICollectionViewCell 中的按钮不起作用