UICollectionView reloadData () заставляет ячейки перекрываться - PullRequest
0 голосов
/ 28 января 2020

Intro

Каждый раз, когда пользователь отправляет комментарий, он загружается в базу данных. После того, как это произошло, collectionView перезагружается. Однако перезагрузка не имеет ожидаемого поведения . Вместо добавления одного комментария в конец collectionView кажется, что он случайным образом складывает некоторые другие ячейки комментариев и отображает только две ячейки комментариев, независимо от того, сколько комментариев есть.

Это На выходе отладчика View вы можете четко видеть, что ячейки collectionView сложены:

Image of the stacked collectionViews

На этом этапе я хотел бы уточнить, что это не ошибка размеров ячеек. Всем им назначен правильный размер, и , если я вызову reloadData в collectionView, в , более поздний момент времени , все ячейки отображаются правильно .

Я думаю, что все станет более ясным, если вы посмотрите на GIF:

Gif of the error

Я действительно понятия не имею, откуда возникла эта ошибка или как ее исправить.

Код

Инициализация collectionView

private lazy var timelineCollectionView: UICollectionView = {
    let flowLayout = UICollectionViewFlowLayout()
    flowLayout.scrollDirection = .vertical
    flowLayout.estimatedItemSize = CGSize(width: self.view.frame.width, height: 10)
    flowLayout.minimumInteritemSpacing = 0
    flowLayout.minimumLineSpacing = 0

    let cv = UICollectionView(frame: .zero, collectionViewLayout: flowLayout)
    cv.contentInsetAdjustmentBehavior = .never
    cv.backgroundColor = .clear
    cv.scrollIndicatorInsets = UIEdgeInsets(top: self.coloredTitleBarHeight - self.getStatusBarHeight(), left: 0, bottom: 0, right: 0)

    cv.delegate = self
    cv.dataSource = self
    cv.register(TLContentCell.self, forSupplementaryViewOfKind: UICollectionView.elementKindSectionHeader, withReuseIdentifier: "content-header-cell")
    cv.register(TLContentCell.self, forCellWithReuseIdentifier: "comment-cell")

    return cv
}()

Код методов UICollectionViewDelegate:

func collectionView(_ collectionView: UICollectionView, viewForSupplementaryElementOfKind kind: String, at indexPath: IndexPath) -> UICollectionReusableView {
    let cell = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: "content-header-cell", for: indexPath) as! TLContentCell
    cell.isHeaderCell = true
    cell.timelineContent = tlContentItem
    cell.delegate = self
    cell.isUserInteractionEnabled = true
    return cell
}

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

func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
    let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "comment-cell", for: indexPath) as! TLContentCell
    cell.delegate = self
    cell.timelineContent = TLContent(nativeContentItem: commentItems[indexPath.row])
    return cell
}

func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, referenceSizeForHeaderInSection section: Int) -> CGSize {
    let indexPath = IndexPath(row: 0, section: section)
    let headerView = self.collectionView(collectionView, viewForSupplementaryElementOfKind: UICollectionView.elementKindSectionHeader, at: indexPath) as! TLContentCell


    return headerView.contentView.systemLayoutSizeFitting(CGSize(width: collectionView.frame.width, height: UIView.layoutFittingExpandedSize.height),
    withHorizontalFittingPriority: .required, // Width is fixed
    verticalFittingPriority: .fittingSizeLevel) // Height can be as large as needed
}

Код функции обработчика загрузки комментариев:

@objc func submitComment() {

    submitCommentButton.isEnabled = false
    submitCommentButton.backgroundColor = ColorCodes.lightGray

    guard let user = Auth.auth().currentUser else {
        print("No user detected. Redirecting to the login screen!")
        self.displayWelcomeScreen()
        return
    }

    guard commentTextView.text.count > 0, let commentContent = commentTextView.text else { print("Submission of comment aborted due to empty content."); return }

    commentTextView.resignFirstResponder()
    commentTextView.text = ""
    calculateTextViewSize()

    ContentUploader.uploadComment(uid: user.uid, content: NativeContentBase(msg: commentContent, usersTagged: [], topicsTagged: [], mediaAssigned: []), referencedContent: tlContentItem.nativeContent.contentId) { (error, comment)  in
        if let err = error {
            print("An error occured during the comment upload: ", err)
            return
        }

        print("Successfully uploaded comment!")
        self.commentItems.append(comment)

        DispatchQueue.main.async {
            print(self.commentItems.count)
            self.timelineCollectionView.reloadData()
        }
    }

    print("Comment scheduled for submission!")
}

Я также убедился, что я Я нахожусь в основном потоке при вызове функции reloadData (). Однако странное поведение сохраняется.

Чтобы настроить contentInset и scrollIndicatorInsets collectionView на отображение клавиатуры, Я использую эти две функции :

private func adjustScrollBehavior() {
    let window = UIApplication.shared.windows.filter {$0.isKeyWindow}.first
    let bottomSafeAreaHeight = window?.safeAreaInsets.bottom ?? 0

    // adjust the content Inset of the timelineCollectionView
    let heightOfCommentSection: CGFloat = commentTextViewHeightAnchor.constant + abs(commentTextViewBottomAnchor.constant) + 8 // get the absolute value of the bottomAnchor's constant as it would be negative
    timelineCollectionView.contentInset = UIEdgeInsets(top: 0, left: 0, bottom: heightOfCommentSection + bottomSafeAreaHeight, right: 0) // does not automatically take care of safe area insets
    timelineCollectionView.scrollIndicatorInsets = UIEdgeInsets(top: 0, left: 0, bottom: heightOfCommentSection, right: 0) // automatically takes care of safe area insets
}

func calculateTextViewSize() {
    let minimumSize = commentTextView.layoutMargins.top + commentTextView.layoutMargins.bottom + commentTextView.font!.lineHeight
    let fixedWidth = self.view.frame.width - 32
    let maximumSize: CGFloat = 155
    let newSize = commentTextView.sizeThatFits(CGSize(width: fixedWidth, height: CGFloat.greatestFiniteMagnitude))
    print(newSize)
    if newSize.height > minimumSize && newSize.height <= maximumSize {
        commentTextViewHeightAnchor.constant = newSize.height
    } else {
        commentTextViewHeightAnchor.constant = newSize.height > minimumSize ? maximumSize : minimumSize
    }
    adjustScrollBehavior()
}

Закрытие

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

Большое спасибо за вашу помощь:)

...