🔹 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를 갱신
'Project > MovieClip' 카테고리의 다른 글
🔨 검색결과 내의 영화, 티비의 장르 가져오는 부분 개선 (0) | 2025.02.24 |
---|---|
🔥 MVVM + Combine을 통한 검색기능 구현 2편 구현 순서? (0) | 2025.02.24 |
🤔 reloadData() 함수의 역할 및 동작 방식 (0) | 2025.02.24 |
🔥 MVVM + Combine을 통한 검색기능 구현 1편 패턴 비교 (0) | 2025.02.24 |
✅ MVVM + Combine로 설계한 검색에서 번역 기능 적용하는 최적 방법 (0) | 2025.02.23 |