Smooth TableView and CollectionView Infinite Scrolling Using Prefetch DataSource
prefetch
함수 사용prefetch
델리게이트 함수를 통해 특정 인덱스 패스에 존재한느 모델이 사용할 네트워킹을 사전에 실행 private var collectionView: UICollectionView!
private var dataSource: UICollectionViewDiffableDataSource<Section, PhotoModel>!
private var cellRegistration: UICollectionView.CellRegistration<PhotoCollectionViewCell, PhotoModel>!
private lazy var listLayout: UICollectionViewLayout = {
var listConfig = UICollectionLayoutListConfiguration(appearance: .insetGrouped)
listConfig.trailingSwipeActionsConfigurationProvider = {
[weak self] indexPath -> UISwipeActionsConfiguration? in
guard let model = self?.dataSource.itemIdentifier(for: indexPath) else { return nil }
return .init(actions: [.init(style: .destructive, title: "Delete", handler: { [weak self] _, _, completion in
self?.viewModel?.delete(model: model)
completion(true)
})])
}
return UICollectionViewCompositionalLayout.list(using: listConfig)
}()
diffable
데이터 소스를 사용하기 위해 미리 선언 private func setCollectionView() {
collectionView = .init(frame: view.bounds, collectionViewLayout: listLayout)
collectionView.autoresizingMask = [.flexibleHeight, .flexibleWidth]
view.addSubview(collectionView)
collectionView.delegate = self
collectionView.prefetchDataSource = self
collectionView.isPrefetchingEnabled = true
cellRegistration = .init(handler: { cell, indexPath, model in
cell.configure(with: model)
})
dataSource = .init(collectionView: collectionView, cellProvider: { [weak self] collectionView, indexPath, item in
guard let self = self else { return nil }
let cell = collectionView.dequeueConfiguredReusableCell(using: self.cellRegistration, for: indexPath, item: item)
self.viewModel?.prefetch(model: item)
return cell
})
}
prefetchDataSource
를 통해 특정한 셀이 display
되기 전에 사전 로드할 데이터를 캐치 가능cellRegistration
, dataSource
를 기존의 컬렉션 뷰 UI를 그리는 방법과 달리 컴플리셔 핸들러를 통해 설정extension PhotosViewController: UICollectionViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
let offsetY = scrollView.contentOffset.y
guard collectionView.frame.size.height > 0 else { return }
if offsetY + collectionView.frame.size.height >= collectionView.contentSize.height - 200 {
viewModel?.fetchImages()
}
}
}
infinite scrolling
을 통해 200 픽셀 정도로 현재 컬렉션 뷰 최하단 부를 스크롤할 경우 자동으로 현 시점의 쿼리한 데이터를 더 불러오도록 설정다운로드로 인해 상당히 메모리 부하가 심한데,
full
로 설정되어 있는 이미지 파일을 그대로 다운로드받기 때문. 리사이즈 또는 다운샘플링이 필요한 순간!