Элементы UICollectionView. Данные искажаются после прокрутки в Swift 4.2. - PullRequest
0 голосов
/ 14 ноября 2018

Я пытаюсь реализовать экран чата с использованием UICollectionView, и данные отображаются в соответствии с ожиданиями.Однако, когда я пытаюсь прокрутить его несколько раз, мои данные искажаются, как показано на скриншотах.Кто-нибудь может подсказать, что идет не так и как это решить?Спасибо!

Сначала отображаются:

screenshot at start

После прокрутки несколько раз отображается:

screenshot after scrolling a bit

Код всех методов, связанных с UICollectionView, которые я использую:

func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
    let count = chatCategoriesArray.messages.count
    if count != 0 {
        return count
    }
    return 0
}

var allCellsHeight: CGFloat = 0.0
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: cellId, for: indexPath) as! ChatLogMessageCell
    cell.messageTextView.text = chatCategoriesArray.messages[indexPath.item]
    let size = CGSize(width: 250, height: 1000)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    let estimatedFrame = NSString(string: chatCategoriesArray.messages[indexPath.item]).boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18)], context: nil)

    if chatCategoriesArray.senderIds[indexPath.item] == "s_\(self.studentInstance.tutorIdFound)"{
        cell.profileImageView.image = UIImage(named: "three.png")
        cell.profileImageView.isHidden = false
        cell.messageTextView.frame = CGRect(x: 48 + 8, y:0, width: estimatedFrame.width + 16, height: estimatedFrame.height + 20)
        cell.textBubbleView.frame = CGRect(x: 48, y: 0, width: estimatedFrame.width + 16 + 8, height: estimatedFrame.height + 20)
        self.currentCellWidth = Double(estimatedFrame.width + 16 + 8)
        cell.textBubbleView.backgroundColor = .white
        cell.addSubview(cell.profileImageView)
        cell.addConstraintsWithFormat(format: "H:|-8-[v0(30)]", views: cell.profileImageView)
        cell.addConstraintsWithFormat(format: "V:[v0(30)]|", views: cell.profileImageView)
    }
    else{
        cell.profileImageView.image = UIImage(named: "two.png")
        cell.textBubbleView.backgroundColor = UIColor(r: 28, g:168, b:261)
        cell.messageTextView.frame = CGRect(x: view.frame.width - estimatedFrame.width - 16 - 46, y:0, width: estimatedFrame.width + 16, height: estimatedFrame.height + 20)
        cell.messageTextView.textColor = .white
        cell.textBubbleView.frame = CGRect(x: view.frame.width - estimatedFrame.width - 16 - 8 - 46, y: 0, width: estimatedFrame.width + 16 + 8, height: estimatedFrame.height + 20)
        self.currentCellWidth = Double(estimatedFrame.width + 16 + 8)
        cell.addSubview(cell.profileImageView)
        cell.addConstraintsWithFormat(format: "H:[v0(30)]-8-|", views: cell.profileImageView)
        cell.addConstraintsWithFormat(format: "V:[v0(30)]|", views: cell.profileImageView)
    }
    allCellsHeight += cell.frame.height
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, insetForSectionAt section: Int) -> UIEdgeInsets {

    if allCellsHeight < (collectionView.frame.height){
        return UIEdgeInsets(top: view.frame.height - allCellsHeight, left: 0, bottom: 0, right: 0)
    }
    else {
        return UIEdgeInsets(top: 8, left: 0, bottom: 0, right: 0)
    }
}
func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {

    let size = CGSize(width: 250, height: 1000)
    let options = NSStringDrawingOptions.usesFontLeading.union(.usesLineFragmentOrigin)
    let estimatedFrame = NSString(string: chatCategoriesArray.messages[indexPath.item]).boundingRect(with: size, options: options, attributes: [NSAttributedString.Key.font: UIFont.systemFont(ofSize: 18)], context: nil)
    return CGSize(width: view.frame.width, height: estimatedFrame.height + 20)
}

Ответы [ 2 ]

0 голосов
/ 14 ноября 2018

Коллекционные ячейки используются повторно.Это означает, что при прокрутке вверх / вниз ячейки, которые становятся невидимыми, удаляются из иерархии и ставятся в очередь для повторного использования.Затем представление коллекции снова вызывает cellForItem: для элементов, которые становятся видимыми.dequeueReusableCell не всегда создает новый экземпляр.Обычно он возвращает только ячейку, которая стала невидимой для вас, чтобы настроить ее снова с новыми данными.

Если вы добавляете виды / ограничения во время установки, вы должны обязательно удалить те, которые вы добавили ранее,в противном случае ячейка будет иметь повторяющиеся представления и конфликтующие ограничения.

Также обратите внимание, что allCellsHeight не может работать так.cell.frame.height не будет корректным сразу после установки (до фактического размещения), и поскольку метод может вызываться несколько раз для одного и того же элемента, вы не можете просто добавить глобальную переменную.Вместо этого вы должны использовать collectionView.contentSize.height.

0 голосов
/ 14 ноября 2018

Это классическая проблема с клетками многократного использования.Это происходит потому, что в представлении коллекции повторно используются настройки ячеек получателя для создания окна сообщения отправителя.

Я предлагаю вам использовать две разные ячейки для отправителя и получателя.С ограничением, установленным при первой загрузке.Это также окажет положительное влияние на производительность.

Проверьте следующее изображение, чтобы понять, как использовать 2 ячейки.

...