WordListViewModel에서 검색과 필터링, 정렬 기능 추가.
WordListViewController는 ViewModel과 UI를 Rx를 사용해 데이터 바인딩.
필터링된 데이터를 실시간으로 TableView에 반영하고, 사용자 입력에 따라 외움 상태를 동적으로 관리.
검색 및 필터링 기능
검색: searchBar의 입력값이 ViewModel의 searchQuery에 바인딩.
필터링:
showMemorizedOnly 버튼으로 외운 단어만 표시하거나 전체 보기 가능.
검색어와 외움 상태를 조합하여 데이터를 필터링한 후 TableView에 반영.
결과가 없을 때 noResultsLabel로 사용자에게 안내.
정렬 기능
ViewModel에 정렬 메서드 추가 (sortVocabularies(by:)).
정렬 옵션:
이름 오름차순 (nameAscending)
이름 내림차순 (nameDescending)
외운 단어 우선 (memorizedFirst).
TableView에서 실시간 정렬 적용 가능.
외움 상태 토글
각 단어 셀의 외움 버튼 클릭 시, ViewModel에서 toggleMemorizeState(at:) 호출.
외움 상태가 변경된 단어는 즉시 UI에 반영.
네트워크 데이터 연동
Firebase Realtime Database에서 단어 데이터 가져오기.
성공 시: 데이터를 BehaviorRelay에 저장 및 UI 반영.
실패 시: 에러 메시지를 사용자에게 전달(errorMessage).
UI와 ViewModel 데이터 바인딩
RxSwift를 사용하여 ViewModel 데이터를 실시간으로 관찰:
filteredVocabularies: 필터링된 단어 목록을 TableView와 연동.
errorMessage: 네트워크 요청 실패 시 에러 메시지 처리.
Observable.combineLatest(vocabularyRelay, searchQuery, showMemorizedOnly)
.map { vocabularies, query, showMemorizedOnly in
vocabularies.filter { vocab in
let matchesQuery = vocab.name.lowercased().contains(query.lowercased()) ||
vocab.definition.lowercased().contains(query.lowercased())
let matchesFilter = !showMemorizedOnly || vocab.didMemorize
return matchesQuery && matchesFilter
}
}
.bind(to: filteredVocabularyRelay)
.disposed(by: disposeBag)
searchBar.rx.text.orEmpty
.bind(to: viewModel.searchQuery)
.disposed(by: disposeBag)
filterButton.rx.tap
.withLatestFrom(viewModel.showMemorizedOnly)
.map { !$0 }
.bind(to: viewModel.showMemorizedOnly)
.disposed(by: disposeBag)
viewModel.filteredVocabularies
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] vocabularies in
self?.noResultsLabel.isHidden = !vocabularies.isEmpty
self?.tableView.reloadData()
})
.disposed(by: disposeBag)