这个问题对我来说很难调试,但我很容易重现。我不明白。
问题在于:
有时,某些聊天消息中的文字颜色相反。我必须做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>