Как работать с разделом пустых элементов в UICollectionView CompositionalLayout

#ios #swift #uicollectionview #uicollectionviewcompositionallayout

Вопрос:

Я пытаюсь создать представление коллекции с композиционной компоновкой, состоящей из нескольких разделов

но если в разделах есть пустые элементы, как я могу с этим справиться?

если элемент пуст, я не хочу показывать этот раздел

 UICollectionViewCompositionalLayout { (section, env) -> NSCollectionLayoutSection? in
  // do I have to code in this area? 
}
 

введите описание изображения здесь

Комментарии:

1. У вас есть пустой массив источников данных для первого раздела (например [[],[image, image, image ...]] )? Или внутри него есть элементы (которые не видны, возможно, потому, что изображение равно нулю)?

Ответ №1:

Если вы также используете UICollectionViewDiffableDataSource, вы можете иметь дело с пустыми разделами при создании/обновлении снимков — добавляйте только разделы с элементами в нем.

В своем проекте я делаю что-то вроде этого:

 func performQuery(animate: Bool) {
    var currentSnapshot = NSDiffableDataSourceSnapshot<Section, ViewCell>()
    
    if !calendars.isEmpty {
        currentSnapshot.appendSections([Section(name: "main")])
        currentSnapshot.appendItems(calendars, toSection: Section(name: "main"))
    }

    if !lifeCals.isEmpty {
        currentSnapshot.appendSections([Section(name: "life")])
        currentSnapshot.appendItems(lifeCals, toSection: Section(name: "life"))
    }
    
    dataSource.apply(currentSnapshot, animatingDifferences: animate)
}
 

Таким образом, если у пользователя 0 календарей жизни, раздела «жизнь» не будет.

Ответ №2:

У меня была та же проблема, и я решил ее так:

 import UIKit

final class CollectionViewCompositionalLayout: UICollectionViewCompositionalLayout {
    override init(sectionProvider: @escaping UICollectionViewCompositionalLayoutSectionProvider) {
        weak var weakSelf: CollectionViewCompositionalLayout?

        super.init { section, environment in
            guard
                let strongSelf = weakSelf,
                let collectionView = strongSelf.collectionView,
                let dataSource = collectionView.dataSource,
                dataSource.collectionView(collectionView, numberOfItemsInSection: section) == 0
            else {
                return sectionProvider(section, environment)
            }
            return strongSelf.emptySectionLayout()
        }

        weakSelf = self
    }

    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

extension CollectionViewCompositionalLayout {
    private enum Constants {
        static let size: CGFloat = 0.1
    }

    private func emptySectionLayout() -> NSCollectionLayoutSection {
        let size = NSCollectionLayoutSize(
            widthDimension: .estimated(Constants.size),
            heightDimension: .estimated(Constants.size)
        )
        let item = NSCollectionLayoutItem(
            layoutSize: size
        )
        let group = NSCollectionLayoutGroup.vertical(
            layoutSize: size,
            subitems: [item]
        )
        let emptySectionLayout = NSCollectionLayoutSection(group: group)
        return emptySectionLayout
    }
}
 

Это выглядит не очень хорошо, но работает довольно хорошо 🙂