본문 바로가기

Project/MovieClip

🤔 배우의 출연작 조회 (영화, 티비)

 

 

🎬 배우 출연작(Credit) 섹션의 구조 정리 및 데이터 흐름

 

✅ 전체적인 흐름

  1. PeopleDetatilViewController에서 viewDidLoad()에서 API를 호출하여 배우의 영화 및 TV 출연작 데이터를 가져온다.
  2. 출연작 데이터는 movieCredits, tvCredits 배열에 저장된다.
  3. CreditTableViewCell에서 기본적으로 영화(Movie) 출연작을 표시하고, 버튼을 눌러 TV 출연작으로 변경할 수 있다.
  4. CreditTableViewCell 내부의 UICollectionView에서 출연작을 수평 스크롤로 표시한다.
  5. 컬렉션뷰 아이템을 선택하면 해당 작품의 상세페이지(DetailViewController)로 이동한다.

 

✅ 구현된 주요 로직 정리

1. PeopleDetatilViewController에서 API 요청하여 데이터 저장

 

  • movieCredits & tvCredits 배열에 각각 영화와 TV 출연작 데이터를 저장.
  • API 호출이 완료되면 tableView.reloadData() 실행.

 

class PeopleDetatilViewController: UIViewController {
    
    private let peopleID: Int
    
    // ✅ 영화, 티비 출연작 저장
    private var movieCredits: [MovieCreditCast] = []
    private var tvCredits: [TVCreditCast] = []
    private var creditType: CreditType = .movie  // ✅ 기본값: Movie

    override func viewDidLoad() {
        super.viewDidLoad()
        fetchedPeopleDetailInfo() // API 요청
    }
    
    private func fetchedPeopleDetailInfo() {
        Task {
            do {
                // ✅ 영화, 티비 API 요청 ➡️ 저장
                let movieCredits = try await NetworkManager.shared.getMovieCredits(peopleID: peopleID)
                let tvCredits = try await NetworkManager.shared.getTVCredits(peopleID: peopleID)
                
                DispatchQueue.main.async { [self] in
                    self.movieCredits = movieCredits.cast
                    self.tvCredits = tvCredits.cast
                    self.peopleTableView.reloadData()
                }
            } catch {
                print("❌ 데이터 로드 실패: \(error)")
            }
        }
    }
}

 

 

2. PeopleDetatilViewController에서 UITableView 설정

  • 영화 또는 TV 출연작을 CreditTableViewCell에 전달.
extension PeopleDetatilViewController: UITableViewDelegate, UITableViewDataSource {

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        
        switch PeopleDetailSection.allCases[indexPath.section] {
        
        case .overview:
        
            let cell = tableView.dequeueReusableCell(withIdentifier: PeopleOverviewTableViewCell.reuseIdentifier, for: indexPath) as! PeopleOverviewTableViewCell
            cell.configure(with: koreanBio)
            return cell
            
        // ✅ 출연작에 데이터 전달
        case .filmography:
        
            let cell = tableView.dequeueReusableCell(withIdentifier: CreditTableViewCell.reuseIdentifier, for: indexPath) as! CreditTableViewCell
            
            switch creditType {
            case .movie:
                cell.configure(with: .movie(movieCredits), creditType: .movie)
            case .tv:
                cell.configure(with: .tv(tvCredits), creditType: .tv)
            }
            
            cell.delegate = self
            return cell
        }
    }
}

 

3. CreditTableViewCell에서 데이터 처리 및 UI 구성

  • configure()에서 CreditInfos에 따라 영화 또는 TV 데이터를 설정하고 컬렉션뷰를 리로드.
  • didTapCalledMovie() & didTapCalledTV() 클릭 시 delegate?.didTapCategoryButton() 호출.
class CreditTableViewCell: UITableViewCell {

    // MARK: - Variable
    static let reuseIdentifier: String = "CreditTableViewCell"
    
    // ✅ 현재 선택된 카테고리 관리 
    private var creditType: CreditType = .movie
    
    // ✅ CreditTableViewCell에 전달할 데이터 형식
    private var creditItems: CreditInfos?

    weak var delegate: CreditTableViewCellDelegate?
    
    
    // MARK: - UI Component
    private lazy var calledMovieCreditButton: UIButton = categoryButton(with: "Movie", action: #selector(didTapCalledMovie))
    private lazy var calledTVCreditButton: UIButton = categoryButton(with: "TV", action: #selector(didTapCalledTV))
    
    private let creditCollectionView: UICollectionView = {
        let layout = UICollectionViewFlowLayout()
        layout.scrollDirection = .horizontal
        layout.itemSize = CGSize(width: 250, height: 180)
        layout.minimumLineSpacing = 10
        let collectionView = UICollectionView(frame: .zero, collectionViewLayout: layout)
        return collectionView
    }()


    // MARK: - Init
    override init(style: UITableViewCell.CellStyle, reuseIdentifier: String?) {
        super.init(style: style, reuseIdentifier: reuseIdentifier)
        contentView.addSubview(buttonStackView)
        contentView.addSubview(creditCollectionView)
        setupCollectionViewDelegate()
    }

    
    // MARK: - Function
    func configure(with creditInfos: CreditInfos, creditType: CreditType) {
        self.creditItems = creditInfos
        self.creditType = creditType
        DispatchQueue.main.async {
            self.creditCollectionView.reloadData()
            self.updateButtonState()
        }
    }
    
    private func updateButtonState() {
        UIView.animate(withDuration: 0.3) { [self] in
            switch creditType {
            case .movie:
                calledMovieCreditButton.configuration?.baseBackgroundColor = .systemBlue
                calledTVCreditButton.configuration?.baseBackgroundColor = .systemGray
            case .tv:
                calledMovieCreditButton.configuration?.baseBackgroundColor = .systemGray
                calledTVCreditButton.configuration?.baseBackgroundColor = .systemBlue
            }
        }
    }


	// MARK: - Action
    @objc private func didTapCalledMovie() {
        delegate?.didTapCategoryButton()
    }

    @objc private func didTapCalledTV() {
        delegate?.didTapCategoryButton()
    }
}

 

4. CreditCollectionViewCell에서 개별 아이템 표시

  • CreditCollectionViewCell에서 영화 또는 TV 아이템을 표시하고 클릭 시 didTapImage()를 실행.
class CreditCollectionViewCell: UICollectionViewCell {
    
    static let reuseIdentifier: String = "CreditCollectionViewCell"
    
    private var selectedContentId: Int?
    private var selectedContentType: ContentType?
    
    weak var delegate: CreditCollectionViewCellDelegate?
    
    func configure(with content: CreditInfo) {
        switch content {
        case .movie(let movieDetail):
            self.selectedContentId = movieDetail.id
            self.selectedContentType = .movie
        case .tv(let tvDetail):
            self.selectedContentId = tvDetail.id
            self.selectedContentType = .tv
        }
    }
    
    @objc private func didTapCreditImage() {
        guard let selectedContentId = selectedContentId, let selectedContentType = selectedContentType else { return }
        delegate?.didTapImage(with: selectedContentId, contentType: selectedContentType)
    }
}

 

5. PeopleDetatilViewController에서 델리게이트 처리

 

  • didTapCategoryButton()에서 creditType.toggle()을 통해 영화/TV 전환.
  • didTapImage()에서 DetailViewController로 이동.

 

extension PeopleDetatilViewController: CreditTableViewCellDelegate {
    
    func didTapCategoryButton() {
        creditType.toggle()  // Movie ↔ TV 전환
        DispatchQueue.main.async {
            self.peopleTableView.reloadData()
        }
    }
    
    func didTapImage(with contentID: Int, contentType: ContentType) {
        let detailVC = DetailViewController(contentID: contentID, contentType: contentType)
        navigationController?.pushViewController(detailVC, animated: true)
    }
}

 


🎬 출연작 데이터 관리 및 구분하는 enum 설명

 

CreditType, CreditInfos, CreditInfo의 역할

배우의 출연작 데이터는 영화(Movie)TV(TV Show) 로 나뉜다.
이 데이터를 구분하고, UITableView 및 UICollectionView에서 동적으로 처리하기 위해 열거형(enum)을 사용한다.

enum CreditType {
    case movie
    case tv
    
    mutating func toggle() {
        self = (self == .movie) ? .tv : .movie
    }
}

 

📌 역할

  • 현재 CreditTableViewCell에서 표시할 출연작이 영화인지, TV인지 구분하는 현재 선택된 상태.
  • toggle() 메서드를 사용하여 영화 <-> TV 전환이 가능.
var creditType: CreditType = .movie
creditType.toggle()  // 현재 타입이 movie라면 tv로 변경, tv라면 movie로 변경
print(creditType)  // tv

🏗 어디서 사용되는가?

  • PeopleDetatilViewController에서 creditType을 저장하고 있음.
  • didTapCategoryButton()에서 creditType.toggle()을 실행하여 영화/TV를 전환.
  • CreditTableViewCell에서 creditType을 기반으로 configure()에서 데이터 설정.

 

 

✅ 2. CreditInfos - CreditTableViewCell에 전달할 데이터 형식

enum CreditInfos {
    case movie([MovieCreditCast])
    case tv([TVCreditCast])
}

📌 역할

  • CreditTableViewCell에서 영화 목록 또는 TV 목록을 받을 때 사용.
  • API에서 가져온 데이터를 영화 리스트 또는 TV 리스트로 감싸서 CreditTableViewCell로 전달.
let movieList: [MovieCreditCast] = [...]  // API에서 받은 영화 출연작 배열
let creditInfo = CreditInfos.movie(movieList)

🏗 어디서 사용되는가?

  • PeopleDetatilViewController에서 출연작 데이터를 CreditTableViewCell로 전달할 때 사용.
  • CreditTableViewCellconfigure()에서 이 타입을 기준으로 컬렉션뷰를 업데이트.

 

✅ 3. CreditInfo - CreditCollectionViewCell에서 개별 아이템을 저장

enum CreditInfo {
    case movie(MovieCreditCast)
    case tv(TVCreditCast)
}

 

📌 역할

  • UICollectionView의 개별 셀에서 해당 아이템이 영화인지, TV인지 구분.
  • CreditCollectionViewCell에서 사용하여 개별 아이템을 표시.