Lazy Loading UICollectionView Sections

64 Views Asked by At

I have a collectionView which uses UICollectionViewCompositionalLayout. It has 150 Sections and each section can have a random number of items (up to 30) depending what comes back from the API.

I've been trying to lazy load each section using the prefetch API - specifically collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]).

I'm reloading each section once the data is received using collectionView.reloadSections(at: [...]) but when I scroll up and down whilst each section is loading, it's very choppy and slow. I've also dispatched the reload on the main thread and have tried using OperationQueue.

I've also even tried using the DiffableDataSource API but its still slow.

What is the correct way to reload sections, when scrolling and lazy loading, whilst maintaining a smooth scroll experience?

Code Below:


class View: UIView {
    
    var collectionView: UICollectionView!
    
    // Reload section once API returns data
    func reloadCell(at index: Int) {
        self.collectionView.reloadSections(IndexSet(integer: index))
    }
    
    func createLayout() -> UICollectionViewLayout {
        let layout = UICollectionViewCompositionalLayout { (sectionIndex, layoutEnvironment) in
            ...
            return section
        }
        return layout
    }
}

// MARK: - UICollectionViewDelegate, UICollectionViewDataSource, UICollectionViewDelegateFlowLayout
extension ScheduleView: UICollectionViewDelegate,
                        UICollectionViewDataSource,
                        UICollectionViewDelegateFlowLayout,
                        UICollectionViewDataSourcePrefetching {
    
    // Trigger API for sections
    func collectionView(_ collectionView: UICollectionView, prefetchItemsAt indexPaths: [IndexPath]) {
        for indexPath in indexPaths {
            dataSource?.willPresentCell(atIndex: indexPath.section)
        }
    }
    
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return dataSource?.numberOfObjects(for: section) ?? 0
    }

    func numberOfSections(in collectionView: UICollectionView) -> Int {
        return 150
    }
}
0

There are 0 best solutions below