我有时会从UICollectionView单元格中获得奇怪的行为

时间:2018-03-25 15:41:28

标签: ios swift

这个问题对我来说很难调试,但我很容易重现。我不明白。

问题在于:

enter image description here

有时,某些聊天消息中的文字颜色相反。我必须做3次分页才能重现这个bug。总共需要加载80条消息才能显示此错误。我必须几乎一直滚动到顶部,然后慢慢向下滚动,直到“Works”变为黑色。有时它不是黑色,有时它是白色的。此外,气泡颜色和位置始终是正确的,有时仅关闭文本颜色。

我正在尝试创建一个聊天应用程序,并在这样的函数中设置单元格:

    internal func setupCell(cell: MessagesCell, message: Message, indexPath: IndexPath, lastReadMessageIndex: Int, timeLabelHeight: CGFloat) {
        // Setting bubbleWidth for all cells.
        cell.bubbleViewWidthAnchor?.constant = estimateFrame(message: message).width + 20 + 6
        let cellSpacing = calculateCellSpacing(messages: messages, indexPath: indexPath)
        if messageDisplaysTime(messages: messages, indexPath: indexPath) {
            cell.bubbleViewTopAnchor?.constant = timeLabelHeight
            cell.timeLabel.text = Date(timeIntervalSince1970: Double(message.createdTime)).messageTime()
            cell.timeLabel.isHidden = false
        } else {
            cell.bubbleViewTopAnchor?.constant = 0
            cell.timeLabel.isHidden = true
        }
        cell.bubbleViewBottomAnchor?.constant = -cellSpacing
        cell.profileImageViewBottomAnchor?.constant = -cellSpacing
        // Messages from me.
        if message.isFromMe() {
            cell.bubbleView.backgroundColor = MessagesCell.bubbleBlueColor
//            // The reason we have to put it here as well is because cells do get reused, so we have to be careful about resetting the color.
            cell.messageTextView.textColor = .white
            cell.bubbleViewLeftAnchor?.isActive = false
            cell.bubbleViewRightAnchor?.isActive = true
            cell.profileImageView.isHidden = true
            if indexPath.item == lastReadMessageIndex {
                // Need to double check that it is actually viewed because lastReadMessageIndex can be 0 and still not read because of default value.
                if message.isViewed {
                    cell.isViewedImageViewBottomAnchor?.constant = -cellSpacing
                    guard let partnerImageName = user?.imageName else { return }
                    cell.isViewedImageView.loadImage(urlString: User.imageURL(imageName: partnerImageName))
                    cell.isViewedImageView.isHidden = false
                }
            } else {
                cell.isViewedImageView.isHidden = true
            }
        // Messages to me.
        } else {
            cell.isViewedImageView.isHidden = true
            cell.bubbleView.backgroundColor = MessagesCell.bubbleGrayColor
            cell.messageTextView.textColor = .black
            cell.bubbleViewLeftAnchor?.isActive = true
            cell.bubbleViewRightAnchor?.isActive = false
            // Only show profile image for the last message in the chain of messages from partner.
            if isNextMessageFromAnotherSender(messages: messages, indexPath: indexPath) || isLastMessage(messages: messages, indexPath: indexPath) || nextMessageDisplaysTime(messages: messages, indexPath: indexPath) {
                cell.profileImageView.isHidden = false
            } else {
                cell.profileImageView.isHidden = true
            }
        }
        setupBubbleCorners(cell: cell, messages: messages, indexPath: indexPath)
    }

我只是简单地设置气泡的颜色和文本的颜色以及元素的尺寸,这取决于消息是来自我还是来自我。

我添加了这样的新消息:

    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        let topEdge: CGFloat = 0
        guard let contentOffsetY = collectionView?.contentOffset.y else { return }
        let ceiledContentOffsetY = CGFloat(ceil(Double(contentOffsetY)))
        if ceiledContentOffsetY <= topEdge && okToAppendMessages && appendAmount < 3 {
            appendAmount = appendAmount + 1
            okToAppendMessages = false
//            print("Ok to append new messages")
            fetchMessagesForPagination(completion: { (newMessagesArrayReversed: [Message]) in
                if newMessagesArrayReversed.count < self.limit {
                    print("No more messages to load")
                    return
                }
                guard let beforeSize = self.collectionView?.collectionViewLayout.collectionViewContentSize else { return }
                self.messages = newMessagesArrayReversed + self.messages
                self.collectionViewReloadData(scrollToBottom: false)
                guard let afterSize = self.collectionView?.collectionViewLayout.collectionViewContentSize else { return }
                let diff = afterSize.height - beforeSize.height
                guard let contentOffsetX = self.collectionView?.contentOffset.x else { return }
                guard let contentOffsetY = self.collectionView?.contentOffset.y else { return }
                self.collectionView?.contentOffset = CGPoint(x: contentOffsetX, y: contentOffsetY + diff)
                self.okToAppendMessages = true
            })
        }
    }

获取分页消息的方法:

private func fetchMessagesForPagination(completion: @escaping (_ newMessagesArrayReversed: [Message]) -> ()) {
    guard let messageThread = replyTo else { return }
    let urlString = "\(Config.URL)/api/messages/replyTo/\(messageThread)/offset/\(offset)"
    HttpService.get(urlString: urlString, viewController: self) { (json: JSON) in
        var newMessagesArray = [Message]()
        for messagesJSON in json["messages"].arrayValue {
            let message = Message(json: messagesJSON.dictionaryObject ?? [:])
            newMessagesArray.append(message)
        }
        newMessagesArray.reverse()
        self.offset = newMessagesArray.first?.id ?? 0
        completion(newMessagesArray)
    }
}

HttpService.get()是Alamofire的包装。

MessagesCell:

class MessagesCell: BaseCell {

    var message: Message? {
        didSet {
            guard let message = message else { return }

            messageTextView.text = message.message

            // Load only image for messages sent from partner.
            if !message.isFromMe() {
                profileImageView.loadImage(urlString: User.imageURL(imageName: message.fromImage))
            }
        }
    }

    let messageTextView: UITextView = {
        let tv = UITextView()
        tv.font = UIFont.systemFont(ofSize: 16)
        tv.backgroundColor = .clear
//        tv.textColor = .white
        tv.isEditable = false
        return tv
    }()

    let profileImageView: CachedImageView = {
        let imageView = CachedImageView()
        imageView.contentMode = .scaleAspectFill
        imageView.layer.masksToBounds = true
        imageView.layer.cornerRadius = 16
        imageView.isHidden = true
        return imageView
    }()

    let isViewedImageView: CachedImageView = {
        let imageView = CachedImageView()
        imageView.layer.cornerRadius = 8
        imageView.clipsToBounds = true
        imageView.isHidden = true
        return imageView
    }()

    let timeLabel: UILabel = {
        let label = UILabel()
        label.textColor = UIColor.materialGray(level: 500)
//        label.font = UIFont.boldSystemFont(ofSize: 12)
        label.font = UIFont.systemFont(ofSize: 12)
        label.textAlignment = .center
        label.isHidden = true
        return label
    }()

    static let bubbleBlueColor = UIColor.rgb(red: 0, green: 137, blue: 249)
    static let bubbleGrayColor = UIColor.rgb(red: 240, green: 240, blue: 240)

    let bubbleView: UIView = {
        let view = UIView()
//        view.backgroundColor = MessagesCell.bubbleBlueColor
        view.translatesAutoresizingMaskIntoConstraints = false
        view.layer.cornerRadius = 3
//        view.layer.cornerRadius = 16
        view.layer.masksToBounds = true
        return view
    }()

    var isViewedImageViewBottomAnchor: NSLayoutConstraint?

    var profileImageViewBottomAnchor: NSLayoutConstraint?

    var bubbleViewLeftAnchor: NSLayoutConstraint?
    var bubbleViewRightAnchor: NSLayoutConstraint?
    var bubbleViewWidthAnchor: NSLayoutConstraint?
    var bubbleViewTopAnchor: NSLayoutConstraint?
    var bubbleViewBottomAnchor: NSLayoutConstraint?

    override func setupViews() {
        super.setupViews()

        addSubview(profileImageView)
        addSubview(bubbleView)
        bubbleView.addSubview(messageTextView)
        addSubview(isViewedImageView)
        addSubview(timeLabel)

        profileImageView.anchor(top: nil, left: leftAnchor, bottom: nil, right: nil, topConstant: 0, leftConstant: 8, bottomConstant: 0, rightConstant: 0, widthConstant: 32, heightConstant: 32)
        profileImageViewBottomAnchor = profileImageView.bottomAnchor.constraint(equalTo: bottomAnchor)
        profileImageViewBottomAnchor?.isActive = true

        bubbleViewLeftAnchor = bubbleView.leftAnchor.constraint(equalTo: profileImageView.rightAnchor, constant: 8)
        bubbleViewLeftAnchor?.isActive = false

        let rightConstant: CGFloat = -16 - 2 - 2
        bubbleViewRightAnchor = bubbleView.rightAnchor.constraint(equalTo: rightAnchor, constant: rightConstant)
        bubbleViewRightAnchor?.isActive = true

        bubbleViewWidthAnchor = bubbleView.widthAnchor.constraint(equalToConstant: 230)
        bubbleViewWidthAnchor?.isActive = true

        bubbleViewTopAnchor = bubbleView.topAnchor.constraint(equalTo: topAnchor)
        bubbleViewTopAnchor?.isActive = true

        bubbleViewBottomAnchor = bubbleView.bottomAnchor.constraint(equalTo: bottomAnchor)
        bubbleViewBottomAnchor?.isActive = true

        messageTextView.anchor(top: bubbleView.topAnchor, left: bubbleView.leftAnchor, bottom: bubbleView.bottomAnchor, right: bubbleView.rightAnchor, topConstant: 0, leftConstant: 8, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 0)

        isViewedImageView.anchor(top: nil, left: nil, bottom: nil, right: rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: -2, widthConstant: 16, heightConstant: 16)
        isViewedImageViewBottomAnchor = isViewedImageView.bottomAnchor.constraint(equalTo: bottomAnchor)
        isViewedImageViewBottomAnchor?.isActive = true

        timeLabel.anchor(top: nil, left: leftAnchor, bottom: bubbleView.topAnchor, right: rightAnchor, topConstant: 0, leftConstant: 0, bottomConstant: 0, rightConstant: 0, widthConstant: 0, heightConstant: 30)
    }

}

这是我遇到的最烦人的错误之一,我不知道它来自何处,因为它没有任何意义,因为它只是1个消息的textColor,而不是气泡颜色或位置,只是textColor。 / p>

0 个答案:

没有答案