[UIKit] UICollectionView: Prefetch

Junyoung Park·2022년 12월 31일
0

UIKit

목록 보기
140/142
post-thumbnail
post-custom-banner

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
post-custom-banner

0개의 댓글