final class PokemonUseCase {
private let networkManager: NetworkManager
private let disposeBag = DisposeBag()
init(networkManager: NetworkManager = .shared) {
self.networkManager = networkManager
}
func fetchPokemonList(limit: Int, offset: Int) -> Single<PokemonResponse> {
guard let url = APIEndpoint.pokemonListURL(limit: limit, offset: offset) else {
return .error(NetworkError.invalidUrl)
}
return networkManager.fetch(url: url)
}
func fetchPokemonDetail(for urlString: String) -> Single<PokemonDetail> {
guard let url = APIEndpoint.pokemonDetailURL(for: urlString) else {
return .error(NetworkError.invalidUrl)
}
return networkManager.fetch(url: url)
}
func fetchPokemonImage(for id: Int) -> Single<UIImage> {
return networkManager.fetchPokemonImage(for: id)
}
}
final class MainViewModel {
private let disposeBag = DisposeBag()
private let useCase: PokemonUseCase
let pokemonListSubject = BehaviorSubject<[Pokemon]>(value: [])
let pokemonImagesSubject = BehaviorSubject<[Int: UIImage?]>(value: [:])
let pokemonSelected = PublishSubject<Pokemon>()
private var currentPage = 0
private let limit = 20
private var isLoading = false
init(useCase: PokemonUseCase) {
self.useCase = useCase
}
final class DetailViewModel {
private let disposeBag = DisposeBag()
private let useCase: PokemonUseCase
let pokemonDetailSubject = BehaviorSubject<PokemonDetail?>(value: nil)
let pokemonImageRelay = PublishRelay<UIImage?>()
init(useCase: PokemonUseCase) {
self.useCase = useCase
}
MainViewModel과 DetailViewModel이 같은 UseCase를 주입 받고 있다. MainViewModel과 DetailViewModel이 같은 PokemonUseCase를 공유하면서, 각 뷰 모델이 자신에게 필요하지 않은 메서드에 접근 가능한 문제를 해결하고 싶다.
1) 책임 분리
UseCaseProtocols.swift
import UIKit
import RxSwift
protocol PokemonListUseCaseProtocol {
func fetchPokemonList(limit: Int, offset: Int) -> Single<PokemonResponse>
func fetchPokemonImage(for id: Int) -> Single<UIImage>
}
protocol PokemonDetailUseCaseProtocol {
func fetchPokemonDetail(for urlString: String) -> Single<PokemonDetail>
func fetchPokemonImage(for id: Int) -> Single<UIImage>
}
PokeMonUseCase.swift
final class PokemonUseCase: PokemonListUseCaseProtocol, PokemonDetailUseCaseProtocol {
...
}
1) MainViewModel.swift
final class MainViewModel {
private let disposeBag = DisposeBag()
private let useCase: PokemonListUseCaseProtocol
let pokemonListSubject = BehaviorSubject<[Pokemon]>(value: [])
let pokemonImagesSubject = BehaviorSubject<[Int: UIImage?]>(value: [:])
let pokemonSelected = PublishSubject<Pokemon>()
private var currentPage = 0
private let limit = 20
private var isLoading = false
init(useCase: PokemonListUseCaseProtocol) {
self.useCase = useCase
}
2) DetailViewModel.swift
final class DetailViewModel {
private let disposeBag = DisposeBag()
private let useCase: PokemonDetailUseCaseProtocol
let pokemonDetailSubject = BehaviorSubject<PokemonDetail?>(value: nil)
let pokemonImageRelay = PublishRelay<UIImage?>()
init(useCase: PokemonDetailUseCaseProtocol) {
self.useCase = useCase
}