✅ 클로저를 변수 타입으로?
📌 1. (() -> Void)? 타입 해석
var onSearchResultsUpdated: (() -> Void)?
- (() -> Void)?는 "매개변수가 없고, 반환값도 없는 클로저"를 저장하는 옵셔널 변수를 의미함.
- 해석하면?
- () → 매개변수가 없음 (입력 X)
- -> Void → 반환값이 없음 (출력 X)
- ? → 옵셔널 (값이 nil일 수도 있음)
📌 onSearchResultsUpdated는 "어떤 동작을 실행할 수 있지만, 필요하지 않을 수도 있는" 함수(클로저)를 저장하는 변수
📌 2. 사용 예시
✅ ViewModel에서 클로저 실행
class SearchViewModel {
var onSearchResultsUpdated: (() -> Void)? // ✅ 클로저 프로퍼티 선언
private var movies: [Movie] = []
func search(query: String) {
// 검색 결과를 가져온 후 데이터 업데이트
movies = fetchMovies(query: query)
// ✅ 클로저 실행 → ViewController에게 "데이터가 변경되었어!" 라고 알림
onSearchResultsUpdated?()
}
}
- 검색어가 입력되면 search(query:)를 실행
- 데이터(movies)가 업데이트되면 onSearchResultsUpdated?() 호출
- 즉, "내 데이터를 사용하고 있는 객체(ViewController)에게 업데이트됐으니까 UI 바꿔줘!" 라고 알리는 역할
📌 3. ViewController에서 사용하기
✅ ViewModel의 클로저를 ViewController에 연결
class SearchViewController: UIViewController {
private var viewModel = SearchViewModel()
override func viewDidLoad() {
super.viewDidLoad()
bindViewModel() // ✅ 여기서 클로저를 "저장"하는 역할을 함
}
private func bindViewModel() {
// ✅ 클로저를 설정 (데이터가 변경되었을 때 실행할 동작)
viewModel.onSearchResultsUpdated = { [weak self] in
DispatchQueue.main.async {
self?.updateUI()
}
}
}
private func updateUI() {
print("🔄 UI 업데이트!")
}
func updateSearchResults(for searchController: UISearchController) {
guard let query = searchController.searchBar.text, !query.isEmpty else { return }
viewModel.search(query: query) // ✅ 검색 실행
}
}
📌 설명
- bindViewModel()에서 viewModel.onSearchResultsUpdated에 클로저를 대입
- 이 순간에는 onSearchResultsUpdated?()를 실행하는 게 아님.
- "나중에 실행될 클로저를 저장"하는 역할만 함!
- 즉, 검색 결과가 업데이트되었을 때 실행할 행동을 미리 정의하는 것.
- search() 함수가 실행되면 onSearchResultsUpdated?()가 호출되면서 UI 업데이트 트리거됨
📌 실행 순서
1️⃣ viewDidLoad() 실행 → bindViewModel() 실행됨
2️⃣ viewModel.onSearchResultsUpdated에 UI 업데이트를 실행하는 클로저를 저장
3️⃣ 사용자가 검색어를 입력하면 → updateSearchResults(for:)가 호출됨
4️⃣ viewModel.search(query:) 실행
5️⃣ onSearchResultsUpdated?() 실행
6️⃣ ViewController에서 updateUI()가 실행됨! (UI 업데이트)
📌 4. ?(옵셔널)인 이유
var onSearchResultsUpdated: (() -> Void)?
- ViewController에서 bindViewModel()을 실행하지 않으면 onSearchResultsUpdated는 nil 상태
- 클로저를 실행할 때 nil이면 크래시가 발생하기 때문에 안전하게 onSearchResultsUpdated?() 형태로 호출
'Project > MovieClip' 카테고리의 다른 글
❌ 에러 분석 - UICollectionView 2번 dequeue... (0) | 2025.02.23 |
---|---|
🚜 서치 기능 개선 (MVVM + Combine) (0) | 2025.02.22 |
📍 함수의 역할 -> createFeaturedSection() { } (0) | 2025.02.21 |
📍함수의 역할 -> reloadData() { } (0) | 2025.02.21 |
📍 함수의 역할 -> createDataSource() { } (0) | 2025.02.21 |