본문 바로가기

Project/MovieClip

🤔 createDataSource() 메서드에서 "검색 결과 전체보기" 버튼 동작

🔹 1. SearchFooterView의 역할

📌 SearchFooterView는 UICollectionView의 각 섹션(영화, TV, 인물) 하단에 추가되는 버튼을 포함하는 뷰
📌 "검색 결과 전체보기" 버튼을 누르면, 추가 데이터를 로드할 수 있도록 loadMoreAction 클로저를 실행하는 구조

class SearchFooterView: UICollectionReusableView {
        
    // MARK: - Variable
    static let reuseIdentifier: String = "SearchFooterView"
    private var loadMoreAction: (() -> Void)?
    
    
    // MARK: - UI Component
    let moreButton: UIButton = UIButton(type: .system)
    
    
    // MARK: - Init
    override init(frame: CGRect) {
        super.init(frame: frame)
        
        moreButton.setTitle("더보기", for: .normal)
        moreButton.backgroundColor = .systemBlue
        moreButton.setTitleColor(.white, for: .normal)
        moreButton.layer.cornerRadius = 10
        
        addSubview(moreButton)
        moreButton.translatesAutoresizingMaskIntoConstraints = false
        
        NSLayoutConstraint.activate([
            
            moreButton.centerXAnchor.constraint(equalTo: centerXAnchor),
            moreButton.centerYAnchor.constraint(equalTo: centerYAnchor),
            moreButton.leadingAnchor.constraint(equalTo: leadingAnchor),
            moreButton.trailingAnchor.constraint(equalTo: trailingAnchor),
            moreButton.heightAnchor.constraint(equalToConstant: 40)
            
        ])
        
        moreButton.addTarget(self, action: #selector(loadMoreTapped), for: .touchUpInside)
    }
    
    required init?(coder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
    
    func configure(with title: String, loadMoreAction: @escaping () -> Void) {
        self.loadMoreAction = loadMoreAction
        moreButton.setTitle(title, for: .normal)
    }
    
    @objc private func loadMoreTapped() {
        loadMoreAction?()
    }
    
}

 

🔹 SearchFooterView의 동작 방식

🔹 1) "검색 결과 전체보기" 버튼의 loadMoreAction 설정

func configure(with title: String, loadMoreAction: @escaping () -> Void) {
    self.loadMoreAction = loadMoreAction // ✅ 버튼이 눌렸을 때 실행할 클로저 저장
    moreButton.setTitle(title, for: .normal)
}

✅ 이 메서드는 "검색 결과 전체보기" 버튼의 타이틀을 설정하고,
✅ 버튼이 눌렸을 때 실행할 loadMoreAction 클로저를 저장하는 역할을 해.

 

🔹 2) 사용자가 버튼을 클릭하면 loadMoreAction() 실행

@objc private func loadMoreTapped() {
    loadMoreAction?() // ✅ 버튼 클릭 시 저장된 클로저 실행
}

✅ 사용자가 "검색 결과 전체보기" 버튼을 클릭하면, loadMoreAction?()이 실행
✅ loadMoreAction?()은 createDataSource()에서 설정한 각 섹션별 viewModel.loadMore(for:) 메서드를 호출

 

 

🌟 "검색 결과 전체보기" 버튼 동작 예제

🔸 사용자가 "영화" 섹션의 "더보기" 버튼을 클릭했다고 가정

 

✅ SearchFooterView에서 버튼이 클릭됨

@objc private func loadMoreTapped() {
    loadMoreAction?() // ✅ 저장된 클로저 실행
}

 

✅ createDataSource()에서 loadMore(for:) 실행

footer.configure(with: "검색 결과 전체보기") {
    self.viewModel.loadMore(for: .movie) // 🎬 영화 더보기 요청 실행
}

 

✅ SearchViewModel에서 추가 데이터 요청

func loadMore(for type: SearchSection) {
    switch type {
    case .movie:
        guard movies.count < totalMoviesCount else { return }
        fetchMoreMovies()
    case .tv:
        guard tvShows.count < totalTVShowsCount else { return }
        fetchMoreTVShows()
    case .people:
        guard people.count < totalPeopleCount else { return }
        fetchMorePeople()
    }
}

 

✅ fetchMoreMovies()에서 추가 데이터 가져오기

private func fetchMoreMovies() {
    moviePage += 1
    Task {
        do {
            let moreMovies = try await NetworkManager.shared.searchMovie(with: currentQuery, page: moviePage)
            DispatchQueue.main.async {
                self.movies.append(contentsOf: moreMovies.results)
                self.updateLoadMoreStatus()
            }
        } catch {
            print("❌ 추가 영화 로드 실패: \(error.localizedDescription)")
        }
    }
}

 

✅ reloadData() 실행 후 UI 업데이트

private func reloadData() {
    var snapshot = NSDiffableDataSourceSnapshot<SearchSection, SearchItem>()
    
    if !viewModel.movies.isEmpty {
        snapshot.appendSections([.movie])
        snapshot.appendItems(viewModel.movies.map { SearchItem.movie($0) }, toSection: .movie)
    }
    
    dataSource?.apply(snapshot, animatingDifferences: true)
}

 

 

🎯 🚀 최종 정리

✅ "검색 결과 전체보기" 버튼은 SearchFooterView에서 UI를 담당하고
✅ createDataSource()에서 "더보기" 버튼이 클릭될 경우 실행할 loadMoreAction을 설정하고
✅ loadMoreAction이 실행되면 viewModel.loadMore(for:)가 호출되며
✅ fetchMoreMovies() → reloadData() → UI 업데이트 순으로 동작해
이렇게 구현하면 새로운 데이터를 받아올 때 UICollectionViewDiffableDataSource가 자동으로 UI를 갱신