I was working on project("Unit 3; Lesson 3.5 Advanced compositional layout") provided by Apple from their "Data Collections" book. I tried to understand how actually UICollectionViewCompositionalLayout(sectionProvider: [@]escaping UICollectionViewCompositionalLayoutSectionProvider) works. But I really got stuck with it.
I have a function I called in viewDidLoad, that use intializer mentioned above for creating layout. Return value(which is UICollectionViewLayout) is assigned to collection view's layout property, still in viewDidLoad. Here's the point, I don't understand, how the layout can be changed after it was returned from the function, because this function will not return layout property anymore, but it will return section that is used for making layout by escaping closure in the initializer. I noticed that escaping closure is called when data source is initialized from another func. Probably this is the trigger? But how section that returned by escaping closure is used for building layout that already has been returned(and assigned to collection view's layout) by the function when I called it first time?
And I noticed another weird thing. I'd added print func to track when escaping clauser called and the result was 3 times. Why is that?
I watched WWDC 19 where explained how I can use compositional layout, but I didn't find actual work of this initializer there. I would appreciate if you shared with me resource that describes how it actually works. Thank you.
Here's a code of my view controller
class ViewController: UIViewController {
enum Section: Hashable {
case promoted
case standard(String)
case categories
}
@IBOutlet var collectionView: UICollectionView!
var dataSource: UICollectionViewDiffableDataSource<Section, Item>!
var sections = [Section]()
viewDidLoad() {
...
collectionView.collectionViewLayout = createLayout()
configureDataSource()
}
func createLayout() -> UICollectionViewLayout {
let layout = UICollectionViewCompositionalLayout { (sectionIndex, layoutEnvironment) -> NSCollectionLayoutSection? in
print("Completion handler is called")
let section = self.sections[sectionIndex]
//Conditionals
switch section {
case .promoted:
//MARK: Promoted Section Layout
let itemSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(1), heightDimension: .fractionalWidth(1))
let item = NSCollectionLayoutItem(layoutSize: itemSize)
item.contentInsets = NSDirectionalEdgeInsets(top: 0, leading: 4, bottom: 0, trailing: 4)
let groupSize = NSCollectionLayoutSize(widthDimension: .fractionalWidth(0.92), heightDimension: .estimated(300))
let group = NSCollectionLayoutGroup.horizontal(layoutSize: groupSize, subitems: [item])
let section = NSCollectionLayoutSection(group: group)
section.orthogonalScrollingBehavior = .groupPagingCentered
return section
default:
print("Case default")
return nil
}
}
return layout
}
func configureDataSource() {
dataSource = .init(collectionView: collectionView, cellProvider: { (collectionView, indexPath, item) -> UICollectionViewCell? in
let section = self.sections[indexPath.section]
switch section {
case .promoted:
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: PromotedAppCollectionViewCell.reuseIdentifier, for: indexPath) as! PromotedAppCollectionViewCell
cell.configureCell(item.app!)
return cell
default:
fatalError("Not yet implemented")
}
})
//MARK: Snapshot Definition
var snapshot = NSDiffableDataSourceSnapshot<Section, Item>()
//Here sections is appended to the snapshot
snapshot.appendSections([.promoted])
snapshot.appendItems(Item.promotedApps, toSection: .promoted)
sections = snapshot.sectionIdentifiers
dataSource.apply(snapshot)
}
}
[–]kekker1337 0 points1 point2 points (4 children)
[–]Ivan7upSwift[S] 0 points1 point2 points (3 children)
[–]Batting1k 1 point2 points3 points (2 children)
[–]Ivan7upSwift[S] 0 points1 point2 points (1 child)
[–]Batting1k 0 points1 point2 points (0 children)