MainViewController가 DetailViewModel과 DetailViewController의 초기화를 담당하고 있는 방식이 마음에 들지 않는다..
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedPokemon = pokemon[indexPath.row]
let pokemonURL = selectedPokemon.url
let detailViewModel = DetailViewModel(useCase: PokemonUseCase())
detailViewModel.fetchPokemonDetail(for: pokemonURL)
let detailVC = DetailViewController(viewModel: detailViewModel)
navigationController?.pushViewController(detailVC, animated: true)
}
MainViewController가 하위 계층의 세부 구현에 너무 의존적이게 만들어, 계층 간의 의존성이 강하게 결합되는 것 같다.
MVVM에서는 뷰 컨트롤러가 뷰 모델에 의존하지만, 뷰 모델이 뷰 컨트롤러나 다른 뷰 모델의 세부 사항을 알지 못하는 것이 이상적인 것 같다.
네비게이션과 화면 전환 책임을 담당하는 별도의 객체를 만들자
final class AppCoordinator {
private let navigationController: UINavigationController
private let disposeBag = DisposeBag()
init(navigationController: UINavigationController) {
self.navigationController = navigationController
}
func start() {
let useCase = PokemonUseCase()
let mainViewModel = MainViewModel(useCase: useCase)
let mainVC = MainViewController(viewModel: mainViewModel, coordinator: self)
mainViewModel.pokemonSelected
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] selectedPokemon in
self?.navigateToDetail(with: selectedPokemon)
})
.disposed(by: disposeBag)
navigationController.setViewControllers([mainVC], animated: false)
}
func navigateToDetail(with pokemon: Pokemon) {
let useCase = PokemonUseCase()
let detailViewModel = DetailViewModel(useCase: useCase)
detailViewModel.fetchPokemonDetail(for: pokemon.url) // 데이터 초기화
let detailVC = DetailViewController(viewModel: detailViewModel)
navigationController.pushViewController(detailVC, animated: true)
}
}
func collectionView(_ collectionView: UICollectionView, didSelectItemAt indexPath: IndexPath) {
let selectedPokemon = pokemon[indexPath.row]
viewModel.pokemonSelected.onNext(selectedPokemon)
}