📌 주요 출연진 정보를 얻어오는 과정 정리
1️⃣ 개요
영화, TV, 배우에 대한 상세페이지에서 출연진 정보를 받아와 컬렉션뷰에서 보여주는 과정을 정리
✔ 목표:
- movie, tv, people의 타입을 enum(ContentType)을 활용해 일관되게 전달.
- DetailViewController → TopBilledCastTableViewCell → CastCollectionViewCell 로 전달되는 흐름 정리.
✔ 흐름 개요:
- 사용자가 HomeViewController에서 특정 영화/TV/배우 선택 → DetailViewController로 이동.
- DetailViewController에서 fetchContentDetail()을 통해 해당 콘텐츠 상세 정보 요청.
- fetchContentDetail() 내 switch contentType을 사용해 출연진 정보 요청 후 저장
- tableView(cellForRowAt:)에서 TopBilledCastTableViewCell에 출연진 데이터 + 콘텐츠 타입 전달.
- TopBilledCastTableViewCell에서 CastingList enum을 통해 데이터를 컬렉션뷰에 넘김.
- collectionView(cellForItemAt:)에서 출연진 정보를 컬렉션뷰에 표시.
2️⃣ ContentType(enum) 사용해 타입 구분
이 enum을 사용해서 현재 선택된 콘텐츠의 타입을 구분한다.
enum ContentType {
case movie
case tv
case people
}
3️⃣ DetailViewController에서 선택된 콘텐츠 정보를 전달하는 과정
✔ (1) HomeViewController → DetailViewController로 데이터 전달
✅ 설명: contentType: ContentType을 생성자에 전달하여 해당 콘텐츠가 영화인지, TV인지, 배우인지 구분.
// 사용자가 특정 영화를 선택했을 때 상세 페이지로 이동
func homeFeedTableViewCellDidSelectItem(_ cell: HomeFeedTableViewCell, section: Int, index: Int) {
let sectionData = HomeViewController.homeSections[section]
switch sectionData {
case .trendingMovies(let movies):
let selectedMovie = movies[index]
let detailVC = DetailViewController(contentID: selectedMovie.id, contentType: .movie)
navigationController?.pushViewController(detailVC, animated: true)
case .trendingTVs(let tvShows):
let selectedTV = tvShows[index]
let detailVC = DetailViewController(contentID: selectedTV.id, contentType: .tv)
navigationController?.pushViewController(detailVC, animated: true)
case .trendingPeoples(let people):
let selectedPeople = people[index]
let detailVC = DetailViewController(contentID: selectedPeople.id, contentType: .people)
navigationController?.pushViewController(detailVC, animated: true)
}
}
✔ (2) DetailViewController에서 콘텐츠 정보 요청 및 저장
✅ 설명
- fetchContentDetail() 실행 후 콘텐츠 타입(movie, tv, people)에 따라 적절한 데이터 요청 및 저장.
private func fetchContentDetail() {
Task {
do {
var fetchedDetail: ContentDetail?
var fetchedGenres: [String] = []
var fetchedCastingList: TopBilledCastInfoWelcome?
switch contentType {
case .movie:
let movieDetail = try await NetworkManager.shared.getMovieDetailInfo(movieID: contentID)
fetchedDetail = .movie(movieDetail)
fetchedGenres = getGenresFromHomeSection(for: contentID)
// ✅ casting 정보 받아오기
fetchedCastingList = try await NetworkManager.shared.getMovieCastInfo(contentID: contentID)
case .tv:
let tvDetail = try await NetworkManager.shared.getTVDetailInfo(tvID: contentID)
fetchedDetail = .tv(tvDetail)
fetchedGenres = getGenresFromHomeSection(for: contentID)
// ✅ casting 정보 받아오기
fetchedCastingList = try await NetworkManager.shared.getTVCastInfo(contentID: contentID)
case .people:
let peopleDetail = try await NetworkManager.shared.getPeopleDetailInfo(peopleID: contentID)
fetchedDetail = .people(peopleDetail)
fetchedGenres = getGenresFromHomeSection(for: contentID)
}
DispatchQueue.main.async {
self.detailTableHeaderView()
guard let contentDetail = fetchedDetail else { return }
self.contentDetail = contentDetail
// ✅ 출연진 정보 저장
switch contentDetail {
case .movie:
if let castingList = fetchedCastingList {
self.movieTopBilledCastInfo = .movie(castingList)
}
case .tv:
if let castingList = fetchedCastingList {
self.movieTopBilledCastInfo = .tv(castingList)
}
case .people:
break
}
self.detailTableView.reloadData()
}
} catch {
print("❌ 데이터 로드 실패: \(error)")
}
}
}
✔ (3) tableView(cellForRowAt:)에서 출연진 정보를 TopBilledCastTableViewCell로 전달
✅ 설명
- TopBilledCastTableViewCell에 출연진 정보(CastingList)를 configure()를 통해 전달.
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let sectionType = DetailSection.allCases[indexPath.section]
switch sectionType {
case .overview:
guard let cell = tableView.dequeueReusableCell(withIdentifier: OverviewTableViewCell.reuseIdentifier, for: indexPath) as? OverviewTableViewCell else { return UITableViewCell() }
if let contentDetail = contentDetail {
cell.configure(with: contentDetail)
}
return cell
case .actor:
guard let cell = tableView.dequeueReusableCell(withIdentifier: TopBilledCastTableViewCell.reuseIdentifier, for: indexPath) as? TopBilledCastTableViewCell else { return UITableViewCell() }
// ✅ 출연진 데이터 전달
switch contentType {
case .movie:
if let castingInfo = movieTopBilledCastInfo {
cell.configure(with: castingInfo)
}
case .tv:
if let castingInfo = movieTopBilledCastInfo {
cell.configure(with: castingInfo)
}
case .people:
break
}
return cell
default:
let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)
cell.textLabel?.text = "Test"
cell.backgroundColor = .white
return cell
}
}
4️⃣ TopBilledCastTableViewCell에서 컬렉션뷰에 콘텐츠 타입 전달
✔ (1) CastingList enum 정의
enum CastingList {
case movie(TopBilledCastInfoWelcome)
case tv(TopBilledCastInfoWelcome)
case people
}
✔ (2) TopBilledCastTableViewCell에서 configure() 메서드 구현
✅ configure(with casting: CastingList)를 통해 출연진 정보를 저장하고 컬렉션뷰 갱신.
class TopBilledCastTableViewCell: UITableViewCell {
static let reuseIdentifier: String = "TopBilledCastTableViewCell"
private var castingList: CastingList?
private let topBilledCastCollectionView: UICollectionView = {
let layout = UICollectionViewFlowLayout()
layout.scrollDirection = .horizontal
layout.itemSize = CGSize(width: 150, height: 200)
layout.minimumLineSpacing = 10
let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
collectionView.showsHorizontalScrollIndicator = true
collectionView.backgroundColor = .clear
return collectionView
}()
func configure(with casting: CastingList) {
self.castingList = casting
topBilledCastCollectionView.reloadData()
}
}
✔ (3) UICollectionView에서 출연진 정보를 사용
✅ castingList를 통해 현재 콘텐츠가 영화인지, TV인지 판별하여 컬렉션뷰 데이터 설정.
extension TopBilledCastTableViewCell: UICollectionViewDelegate, UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
switch castingList {
case .movie(let castInfo):
return castInfo.cast.count
case .tv(let castInfo):
return castInfo.cast.count
default:
return 0
}
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
guard let cell = collectionView.dequeueReusableCell(withReuseIdentifier: CastCollectionViewCell.reuseIdentifier, for: indexPath) as? CastCollectionViewCell else { return UICollectionViewCell() }
switch castingList {
case .movie(let castInfo):
let castMember = castInfo.cast[indexPath.item]
cell.configure(with: castMember)
case .tv(let castInfo):
let castMember = castInfo.cast[indexPath.item]
cell.configure(with: castMember)
default:
break
}
return cell
}
}
📌 정리
- HomeViewController → DetailViewController 이동 시 ContentType을 활용해 타입 전달 ✅
- fetchContentDetail()에서 CastingList 데이터를 요청 후 저장 ✅
- tableView(cellForRowAt:)에서 TopBilledCastTableViewCell에 적절한 데이터 전달 ✅
- TopBilledCastTableViewCell에서 CastingList를 configure()를 통해 컬렉션뷰에 반영 ✅
📌 switch contentDetail을 사용하는 코드 분석
✅ 출연진 정보를 저장할 때 switch contentDetail을 사용해야 하는 이유
- 출연진 정보는 movie와 tv에만 존재하기 때문에, people일 경우를 필터링해야 함.
- movie, tv 출연진 정보를 CastingList enum을 활용해서 적절히 저장.
guard let contentDetail = fetchedDetail else { return }
self.contentDetail = contentDetail
// ✅ 출연진 정보 저장
switch contentDetail {
case .movie:
if let castingList = fetchedCastingList {
self.movieTopBilledCastInfo = .movie(castingList) // 🎥 영화 출연진 정보 저장
}
case .tv:
if let castingList = fetchedCastingList {
self.movieTopBilledCastInfo = .tv(castingList) // 📺 TV 출연진 정보 저장
}
case .people:
break // 🧍 배우는 출연진 정보가 필요 없음
}
📌 switch contentType을 사용하지 않은 이유
switch contentType {
case .movie:
self.movieTopBilledCastInfo = .movie(castingList)
case .tv:
self.movieTopBilledCastInfo = .tv(castingList)
case .people:
break
}
✅ 이렇게 해도 동작은 하지만, contentType을 사용하면 출연진 데이터를 요청하기 전에 콘텐츠의 타입을 확인하는 방식.
✅ switch contentDetail을 사용하면 실제 데이터를 받아온 후(fetchedDetail) 타입을 확인해서 더 안전한 방식
📌 결론
- switch contentDetail을 사용하면 실제 API 응답에서 콘텐츠 데이터를 확인한 후, 타입별로 출연진 정보를 저장할 수 있어서 안전
- contentType을 사용하는 방식보다 더 데이터 중심적인 로직이 됨.
- people은 출연진이 필요 없으므로 배제하는 작업이 필요하기 때문에 switch contentDetail이 적절
'Project > MovieClip' 카테고리의 다른 글
상세 페이지 내에서 영화, 티비 관련한 유사한 내용은 컬렉션뷰로 보여주기 (0) | 2025.02.11 |
---|---|
상세페이지에서 video, poster 데이터를 UICollectionView로 구현 (0) | 2025.02.11 |
테이블의 rowheight을 동적으로 할 때 주의할 점 (0) | 2025.02.10 |
TMDB에서 특정 조건의 video 정보 받아오기 (0) | 2025.02.10 |
✅ UIScrollView 안에 UITableView를 넣는 것이 올바른가? (상세페이지 구현) (0) | 2025.02.09 |