본문 바로가기

Project/MovieClip

테이블의 섹션 별로 다르게 UI 구성

📌 해결해야 할 문제

✅ totalStackView의 arrangedSubviews를 Movie, TV, People에 따라 다르게 구성해야 함

Movie, TV일 때 → [genreLabel, releasedDateLabel]

People일 때 → [titleLabel]

 

🚀 해결 방법

1️⃣ totalStackView의 arrangedSubviews를 동적으로 변경

  • 기존의 totalStackView를 초기화할 때 arrangedSubviews를 미리 지정하지 않음
  • configureCollectionView(_:) 호출 시 적절한 뷰를 totalStackView에 추가
  • 이전에 추가된 arrangedSubviewsremoveAllArrangedSubviews()로 제거하여 중복 방지

 

🔧 개선된 코드

🔹 Step 1: totalStackView 초기화 시 arrangedSubviews 제거 가능하도록 추가

 

✅ 기존의 totalStackView 내에 arrangedSubviews 내용 삭제 

기존 arrangedSubviews를 제거하는 함수 추가 (removeAllArrangedSubviews())

새로운 arrangedSubviews를 설정할 때 이전 뷰를 자동으로 삭제하여 중복 방지

private lazy var totalStackView: UIStackView = {
    let stackView = UIStackView()
    stackView.axis = .vertical
    stackView.spacing = 5
    stackView.alignment = .fill
    stackView.distribution = .fill
    return stackView
}()

// ✅ 기존 arrangedSubviews 제거하는 메서드 추가
private func removeAllArrangedSubviews() {
    for view in totalStackView.arrangedSubviews {
        totalStackView.removeArrangedSubview(view)
        view.removeFromSuperview()
    }
}

 

🔹 Step 2: configureCollectionView(_:)에서 totalStackView 업데이트

func configureCollectionView(_ movie: MovieResult) {
    removeAllArrangedSubviews() // ✅ 기존 View 제거

    releasedDateLabel.text = formatDateString(movie.releaseDate)

    let score = (movie.voteAverage)
    scoreLabel.configure(with: score != 0 ? Int(score * 10) : 100)

    let posterPath = movie.posterPath
    guard let url = URL(string: "https://image.tmdb.org/t/p/w500/\(posterPath)") else { return }
    posterImageView.sd_setImage(with: url, completed: nil)

    genreLabel.text = movie.genreNames?.joined(separator: " / ") ?? "장르 없음"

    // ✅ Movie, TV에서는 genreLabel + releasedDateLabel
    totalStackView.addArrangedSubview(genreLabel)
    totalStackView.addArrangedSubview(releasedDateLabel)
}

// ✅ TV 데이터 설정
func configureCollectionView(_ tv: TVResult) {
    removeAllArrangedSubviews() // ✅ 기존 View 제거

    titleLabel.text = tv.name
    releasedDateLabel.text = formatDateString(tv.firstAirDate)

    let score = (tv.voteAverage)
    scoreLabel.configure(with: score != 0 ? Int(score * 10) : 100)

    let posterPath = tv.posterPath
    guard let url = URL(string: "https://image.tmdb.org/t/p/w500/\(posterPath)") else { return }
    posterImageView.sd_setImage(with: url, completed: nil)

    genreLabel.text = tv.genreNames?.joined(separator: " / ") ?? "장르 없음"

    // ✅ Movie, TV에서는 genreLabel + releasedDateLabel
    totalStackView.addArrangedSubview(genreLabel)
    totalStackView.addArrangedSubview(releasedDateLabel)
}

// ✅ People 데이터 설정 (titleLabel만 사용)
func configureCollectionView(_ people: PeopleResult) {
    removeAllArrangedSubviews() // ✅ 기존 View 제거

    titleLabel.text = people.originalName
    releasedDateLabel.text = "" // ✅ People에서는 releaseDate 사용 안 함

    guard let posterPath = people.profilePath else {
        posterImageView.image = UIImage(systemName: "person.circle")
        return
    }

    guard let url = URL(string: "https://image.tmdb.org/t/p/w500/\(posterPath)") else { return }
    posterImageView.sd_setImage(with: url, completed: nil)

    // ✅ People에서는 titleLabel만 추가
    totalStackView.addArrangedSubview(titleLabel)
}

 

🚀 최종 정리

데이터 타입 totalStackView 구성
Movie, TV genreLabel + releasedDateLabel
People titleLabel

 

removeAllArrangedSubviews()를 사용하여 기존 뷰를 제거하고 새로운 뷰를 설정하여 중복 방지

각 데이터 타입별로 적절한 UI 요소만 totalStackView에 추가하여 유연한 동작 구현

 

 


 

📌 해결해야 할 문제

Movie, TV일 때 → scoreLabel 표시

People일 때 → scoreLabel 제외

scoreLabel을 동적으로 추가/제거해야 함

 

🚀 해결 방법

1️⃣ scoreLabel을 totalStackView 안에 추가하여 동적으로 관리할 수도 있지만, 디자인적으로 위치를 유지해야 하면 그대로 contentView에 유지

2️⃣ scoreLabel을 추가/제거하는 toggleScoreLabel(show:) 메서드를 만들어 필요할 때만 추가/삭제

3️⃣ configureCollectionView(_:)에서 Movie, TV일 때만 scoreLabel을 추가하도록 설정

 

🔧 코드 수정

🔹 Step 1: toggleScoreLabel(show:) 추가

✅ show 값이 true일 때 scoreLabel을 추가, false일 때 제거

✅ contentView.subviews.contains(scoreLabel) 체크하여 중복 추가 방지

private func toggleScoreLabel(show: Bool) {
    if show {
        if !contentView.subviews.contains(scoreLabel) { // ✅ 중복 추가 방지
            contentView.addSubview(scoreLabel)

            NSLayoutConstraint.activate([
                scoreLabel.leadingAnchor.constraint(equalTo: posterImageView.leadingAnchor, constant: 10),
                scoreLabel.topAnchor.constraint(equalTo: posterImageView.topAnchor, constant: 10),
                scoreLabel.heightAnchor.constraint(equalToConstant: 34),
                scoreLabel.widthAnchor.constraint(equalToConstant: 34)
            ])
        }
    } else {
        if contentView.subviews.contains(scoreLabel) { // ✅ 존재하면 제거
            scoreLabel.removeFromSuperview()
        }
    }
}

 

 

🔹 Step 2: configureCollectionView(_:)에서 toggleScoreLabel() 적용

// ✅ Movie 데이터 설정
func configureCollectionView(_ movie: MovieResult) {
    removeAllArrangedSubviews() // ✅ 기존 View 제거
    toggleScoreLabel(show: true) // ✅ Movie에서는 scoreLabel 표시

    ...

    // ✅ Movie, TV에서는 genreLabel + releasedDateLabel
    totalStackView.addArrangedSubview(genreLabel)
    totalStackView.addArrangedSubview(releasedDateLabel)
}

// ✅ TV 데이터 설정
func configureCollectionView(_ tv: TVResult) {
    removeAllArrangedSubviews() // ✅ 기존 View 제거
    toggleScoreLabel(show: true) // ✅ TV에서도 scoreLabel 표시

    ...
    
    // ✅ Movie, TV에서는 genreLabel + releasedDateLabel
    totalStackView.addArrangedSubview(genreLabel)
    totalStackView.addArrangedSubview(releasedDateLabel)
}

// ✅ People 데이터 설정 (scoreLabel 제거)
func configureCollectionView(_ people: PeopleResult) {
    removeAllArrangedSubviews() // ✅ 기존 View 제거
    toggleScoreLabel(show: false) // ✅ People에서는 scoreLabel 제거

    ...

    // ✅ People에서는 titleLabel만 추가
    totalStackView.addArrangedSubview(titleLabel)
}

 

🚀 최종 정리 

toggleScoreLabel(show:)를 사용하여 Movie, TV일 때는 scoreLabel을 추가하고, People일 때는 제거

기존 레이아웃 변경 없이 scoreLabel을 동적으로 관리 가능!

데이터 타입 totalStackView 구성 scoreLabel 표시 여부
Movie, TV genreLabel + releasedDateLabel ✅ 표시 (toggleScoreLabel(show: true))
People titleLabel ❌ 제거 (toggleScoreLabel(show: false))

 

 

33300