본문 바로가기

Project/MovieClip

📍 함수의 역할 -> createDataSource() { }

🔍 createDataSource() { } 

이 메서드는 UICollectionViewDiffableDataSource를 생성하고, 셀과 섹션 헤더를 설정하는 역할

 

  • dataSource = UICollectionViewDiffableDataSource<TvTMDBData, TvResultItem>
    • 섹션 타입: TvTMDBData
    • 아이템 타입: TvResultItem
    • 각 섹션(TvTMDBData) 안에 여러 개의 아이템(TvResultItem)이 포함된다.
  • 셀을 생성 및 구성
    • switch sectionType을 사용하여 각 섹션별로 다른 셀을 반환함.
    • configure(_:with:for:) 메서드를 사용해 적절한 셀을 생성하고 데이터를 적용.
  • 섹션 헤더를 설정
    • dataSource?.supplementaryViewProvider를 사용해 섹션별 헤더 뷰를 구성함.
    • 섹션 정보를 가져와 TVSectionHeader에 적용.

 

private func createDataSource() {
    dataSource = UICollectionViewDiffableDataSource<TvTMDBData, TvResultItem>(collectionView: seriesCollectionView) { collectionView, indexPath, item in

        let tvTMDBResult = item.tvResult
        let sectionType = self.tvCombineSection.combineTMDB[indexPath.section].type ?? .popular

        switch sectionType {
        case .airingToday:
            return self.configure(TvFeaturedCell.self, with: tvTMDBResult, for: indexPath)
        case .onTheAir:
            return self.configure(TVMediumCell.self, with: tvTMDBResult, for: indexPath)
        case .popular:
            return self.configure(TvFeaturedCell.self, with: tvTMDBResult, for: indexPath)
        case .topRated:
            return self.configure(TVSmallCell.self, with: tvTMDBResult, for: indexPath)
        }
    }

    dataSource?.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath in
        guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TVSectionHeader.reuseIdentifier, for: indexPath) as? TVSectionHeader else { return nil }

        guard let firstItem = self?.dataSource?.itemIdentifier(for: indexPath) else { return nil }
        guard let section = self?.dataSource?.snapshot().sectionIdentifier(containingItem: firstItem) else { return nil }

        switch section.type {
        case .airingToday:
            let mainTitle = section.type?.rawValue
            let subTitle = "오늘 방영중 TV"
            sectionHeader.configure(with: mainTitle!, sub: subTitle)
        case .onTheAir:
            let mainTitle = section.type?.rawValue
            let subTitle = "현재 방영 중인 TV"
            sectionHeader.configure(with: mainTitle!, sub: subTitle)
        case .popular:
            let mainTitle = section.type?.rawValue
            let subTitle = "인기 TV"
            sectionHeader.configure(with: mainTitle!, sub: subTitle)
        case .topRated:
            let mainTitle = section.type?.rawValue
            let subTitle = "순위 별 TV"
            sectionHeader.configure(with: mainTitle!, sub: subTitle)
        case .none:
            return nil
        }
        return sectionHeader
    }
}

 

🛠 1. dataSource 정의 부분 분석

dataSource = UICollectionViewDiffableDataSource<TvTMDBData, TvResultItem>(collectionView: seriesCollectionView) { collectionView, indexPath, item in

 

💡 각 파라미터의 의미

  • collectionView → seriesCollectionView 인스턴스 (컬렉션뷰 자체)
  • indexPath → 현재 렌더링할 셀의 섹션과 행(아이템)의 위치 정보
  • item → TvResultItem 인스턴스로, 컬렉션 뷰의 특정 셀에 표시할 데이터

 

let tvTMDBResult = item.tvResult
let sectionType = self.tvCombineSection.combineTMDB[indexPath.section].type ?? .popular

 

 

  • tvTMDBResult → 해당 TvResultItem에서 실제 TV 프로그램 정보를 가져옴.
  • sectionType → indexPath.section을 기준으로 현재 섹션이 어떤 타입인지 확인.

 

🛠 2. dataSource?.supplementaryViewProvider(섹션 헤더 설정)

dataSource?.supplementaryViewProvider = { [weak self] collectionView, kind, indexPath in

 

💡 각 파라미터의 의미

  • collectionView → 컬렉션뷰 자체
  • kind보조 뷰의 종류 (헤더인지 푸터인지 결정)
  • indexPath현재 헤더가 속한 섹션의 위치 정보

 

✅ 헤더 뷰를 가져오기

guard let sectionHeader = collectionView.dequeueReusableSupplementaryView(ofKind: kind, withReuseIdentifier: TVSectionHeader.reuseIdentifier, for: indexPath) as? TVSectionHeader else { return nil }
  • dequeueReusableSupplementaryView를 사용해 TVSectionHeader를 재사용

 

✅ 섹션 타입 가져오기

guard let firstItem = self?.dataSource?.itemIdentifier(for: indexPath) else { return nil }
guard let section = self?.dataSource?.snapshot().sectionIdentifier(containingItem: firstItem) else { return nil }

 

  • firstItem → 해당 섹션에 속한 첫 번째 아이템을 가져옴
  • section → 현재 아이템이 속한 섹션(TvTMDBData)을 가져옴

🔍 snapshot().sectionIdentifier(containingItem:)의 역할

guard let section = self?.dataSource?.snapshot().sectionIdentifier(containingItem: firstItem) else { return nil }

 

📌 1. snapshot()

  • dataSource?.snapshot() → UICollectionViewDiffableDataSource의 **현재 데이터 상태(스냅샷)**를 가져옴.
  • snapshot은 NSDiffableDataSourceSnapshot<SectionIdentifierType, ItemIdentifierType> 타입이며,
    현재 컬렉션뷰가 표시하고 있는 모든 섹션 및 아이템의 계층 구조를 포함하고 있음.

📌 2. sectionIdentifier(containingItem:)

  • snapshot.sectionIdentifier(containingItem: firstItem)
    → 특정 아이템(firstItem)이 속한 섹션을 찾아서 반환.
  • 즉, firstItem이 현재 속해 있는 TvTMDBData(섹션) 인스턴스를 반환함.

이걸 통해 현재 섹션이 무엇인지 알 수 있음!
✅ 그래서 섹션 타입(TvSectionType)을 꺼내와서 switch 문으로 헤더 제목을 설정하는 것.