UICollectionView внутри UITableviewCell дает неправильный contentSizeHeight в первый раз, но становится истинным после прокрутки

У меня есть представление, которое структурировано следующим образом

-Tableview
   - TableviewCell
       - UICollectionView
          - UICollectionViewCell

ячейка uicollectionview определяет тег выравнивания по левому краю с collectionViewFlowLayout следующим образом

class Row {
    var attributes = [UICollectionViewLayoutAttributes]()
    var spacing: CGFloat = 0

    init(spacing: CGFloat) {
        self.spacing = spacing
    }

    func add(attribute: UICollectionViewLayoutAttributes) {
        attributes.append(attribute)
    }

    func tagLayout(collectionViewWidth: CGFloat) {
        let padding = 0
        var offset = padding
        for attribute in attributes {
            attribute.frame.origin.x = CGFloat(offset)
            offset += Int(attribute.frame.width + spacing)
        }
    }
}

class LeftAlignTagCollectionViewFlowLayout: UICollectionViewFlowLayout {
    override func layoutAttributesForElements(in rect: CGRect) -> [UICollectionViewLayoutAttributes]? {
        guard let attributes = super.layoutAttributesForElements(in: rect) else {
            return nil
        }

        var rows = [Row]()
        var currentRowY: CGFloat = -1

        for attribute in attributes {
            if currentRowY != attribute.frame.origin.y {
                currentRowY = attribute.frame.origin.y
                rows.append(Row(spacing: 4))
            }
            rows.last?.add(attribute: attribute)
        }

        rows.forEach {
            $0.tagLayout(collectionViewWidth: collectionView?.frame.width ?? 0)
        }
        return rows.flatMap { $0.attributes }
    }
}

это код в источнике данных cellForRow в ViewController, который обрабатывает табличное представление

let cell = tableView.dequeueReusableCell(withIdentifier: "CollectionTableViewCell") as? CollectionTableViewCell
cell?.setupCell(showFirstItem: true, showSecondItem: true)
cell?.collectionView.reloadData()
cell?.layoutIfNeeded()
let height = cell?.collectionView.collectionViewLayout.collectionViewContentSize.height
cell?.collectionViewHeightConstraint.constant = height ?? 0

я уже вызывал layoutIfNeeded() перед доступом к высоте размера содержимого коллекции и назначал высоту содержимого в ограничение высоты коллекции. я уже установил для isScrollEnabled значение false.

а в CollectionTableViewCell это выглядит так

@IBOutlet weak var collectionView: UICollectionView!
@IBOutlet weak var collectionViewHeightConstraint: NSLayoutConstraint! // Required priority (1000)

private var collectionItem: [String] = []
    
    override func awakeFromNib() {
        super.awakeFromNib()
        setupCollectionView()
        collectionView.dataSource = self
        collectionView.delegate = self
        let layout = LeftAlignTagCollectionViewFlowLayout()
        layout.estimatedItemSize = CGSize(width: 140, height: 40)
        collectionView.collectionViewLayout = layout
    }

    func setupCell(showFirstItem: Bool, showSecondItem: Bool)  {
        setupCollectionItem()
    }

    private func setupCollectionItem(showFirstItem: Bool, showSecondItem: Bool) {
        collectionItem = []
        if showFirstItem {
            let data = "TagNumber1"
            collectionItem.append(data)
        }
        
        if showSecondItem {
            let data = "TagNumber2"
            collectionItem.append(data)
        }
    }

extension CollectionTableViewCell: UICollectionViewDataSource, UICollectionViewDelegateFlowLayout {
    private func setupCollectionView() {
        collectionView.register(UINib(nibName: "CollectionViewCell", bundle: nil), forCellWithReuseIdentifier: "CollectionViewCell")
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return collectionItem.count
    }
    
    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "CollectionViewCell", for: indexPath) as? CollectionViewCell
        cell?.configCell(model: collectionItem[indexPath.row], maxWidth: collectionView.frame.width - 8)
        cell?.setNeedsLayout()
        cell?.layoutIfNeeded()
        return cell ?? UICollectionViewCell()
    }
}

Таким образом, когда я запускаю приведенный выше код, он выдает неправильную высоту размера содержимого при первой загрузке, скажем, около 86,0, но после прокрутки или перезагрузки таблицы во второй раз (у меня есть два раза перезагрузка таблицы, так как есть два метода для вызова API в этот ViewController) он дает правильное число, скажем, цель, которую я хочу, составляет 24,0, поэтому при изменении с первого значения 86,0 на 24,0 это дает сбой в uitableviewcell. и я не могу скрыть представление таблицы, пока не завершу процесс расчета высоты представления коллекции. Еще один момент: если у меня есть только один элемент в collectionItem, он дает правильную высоту содержимого! но когда он превращается в два элемента, проблема проявляется.

жду вашего предложения, спасибо

Стоит ли изучать PHP в 2023-2024 годах?
Стоит ли изучать PHP в 2023-2024 годах?
Привет всем, сегодня я хочу высказать свои соображения по поводу вопроса, который я уже много раз получал в своем сообществе: "Стоит ли изучать PHP в...
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
Поведение ключевого слова "this" в стрелочной функции в сравнении с нормальной функцией
В JavaScript одним из самых запутанных понятий является поведение ключевого слова "this" в стрелочной и обычной функциях.
Приемы CSS-макетирования - floats и Flexbox
Приемы CSS-макетирования - floats и Flexbox
Здравствуйте, друзья-студенты! Готовы совершенствовать свои навыки веб-дизайна? Сегодня в нашем путешествии мы рассмотрим приемы CSS-верстки - в...
Тестирование функциональных ngrx-эффектов в Angular 16 с помощью Jest
В системе управления состояниями ngrx, совместимой с Angular 16, появились функциональные эффекты. Это здорово и делает код определенно легче для...
Концепция локализации и ее применение в приложениях React ⚡️
Концепция локализации и ее применение в приложениях React ⚡️
Локализация - это процесс адаптации приложения к различным языкам и культурным требованиям. Это позволяет пользователям получить опыт, соответствующий...
Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
0
0
44
1
Перейти к ответу Данный вопрос помечен как решенный

Ответы 1

Ответ принят как подходящий

Это по своей сути проблематично по нескольким причинам...

Во-первых, представления коллекций имеют несколько основных преимуществ:

  1. автоматическая прокрутка
  2. управление памятью через повторное использование ячеек

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

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

Если вы ищете uicollectionview inside uitableviewcell dynamic height, вы найдете множество обсуждений и попыток заставить это работать с переменным успехом.

Однако, поскольку, как упоминалось выше, вы являетесь не используется двумя «лучшими функциями» представлений коллекций, вы можете использовать другой подход.

Взгляните на этот ответ на аналогичный вопрос «раскладка тегов». Возможно, вам будет проще работать с: https://stackoverflow.com/a/60588546/6257435

Другие вопросы по теме