[UIKit] UICollectionView: Prefetch

Junyoung Park·2022년 12월 31일
0

UIKit

목록 보기
140/142
post-thumbnail

Prefetching with TableViews (2022) – iOS

Smooth TableView and CollectionView Infinite Scrolling Using Prefetch DataSource

UICollectionView: Prefetch

구현 목표

  • 컬렉션 뷰 prefetch 함수 사용

구현 태스크

  • prefetch 델리게이트 함수를 통해 특정 인덱스 패스에 존재한느 모델이 사용할 네트워킹을 사전에 실행
  • 데이터 캐시를 통한 UI 표시 효율

핵심 코드

	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로 설정되어 있는 이미지 파일을 그대로 다운로드받기 때문. 리사이즈 또는 다운샘플링이 필요한 순간!

profile
JUST DO IT

0개의 댓글

관련 채용 정보