RxSwift와 MVVM 아키텍처를 적용하여 포켓몬 도감을 만드는 것이었다!
필수 구현 기능
Lv.1: NetworkManager 구현 (싱글톤)
Lv.2: MVVM 모델 구현
Lv.3: 포켓몬도감의 MainViewModel 구현, NetworkManager활용
Lv.4: UICollectionView를 활용해 MainViewController 구현
Lv.5: CollectionViewCell select 화면 전환 구현 (상세화면으로 이동)
Lv.6: 상세화면 ViewModel 구현 (DetailViewModel)
Lv.7: DetailViewController 구현
Lv.8: 무한 스크롤 구현
*모든 예외 처리 필수!
포켓몬의 상세 정보 화면에서 이미지를 띄울 때, URL 설정 방식에 대해서 고민했다.
"https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/\(id).png"
URL이 위와 같은 방식으로 설정되에 있는데, 맨 마지막 id 부분을 어떻게 전달하면 좋을지에 대한 고민이었다!
초기 아이디어는,
1. Main에서 받아온 포켓몬의 정보 배열에서, [배열의 인덱스 값 + 1]이 ID 값이 될테니 이를 활용하자!
2. Main 화면에서 Response로 받은 URL중 맨 뒤의 ID 값을 분리해서 사용하자!
MainResponse
{
"name": "bulbasaur",
"url": "https://pokeapi.co/api/v2/pokemon/1/"
}
결론적으로 2번째 방법을 선택했다.
이유는 배열의 인덱스로 사용할 경우, 혹시 모를 예외가 있는 경우(ex) ID가 아예 다른 경우) 에는 또 수정을 해주어야할 거 같아서 아예 안전한 2번째 방법을 채택했다!
func configure(with pokemon: PokemonList) {
// URL에서 포켓몬 ID 추출
if let url = pokemon.url,
let id = Int(url.split(separator: "/").last ?? "0") {
let imageUrlString = "https://raw.githubusercontent.com/PokeAPI/sprites/master/sprites/pokemon/\(id).png"
if let imageUrl = URL(string: imageUrlString) {
DispatchQueue.global().async {
if let data = try? Data(contentsOf: imageUrl),
let image = UIImage(data: data) {
DispatchQueue.main.async {
self.imageView.image = image
}
}
}
}
}
}
하나의 이미지만을 위해서 코드를 작성하는 것이 효율적인지 비효율적인지 . . . 모르겠다 ㅜ_ㅜ
이 부분은 아직도 고민 중이다!!!!
- RxSwift란? 왜 사용하는가?
RxSwift는 비동기 프로그래밍을 위한 라이브러리입니다.
RxSwift를 사용하여 비동기 작업을 선언적으로 처리하고 복잡한 콜백을 단순화하며,
데이터 바인딩과 이벤트 조합을 쉽게 구현할 수 있습니다.
- MVVM의 장단점
MVVM의 장점은 View와 비즈니스 로직을 분리하여 테스트와 코드 재사용이 용이하고 데이터 바인딩을 통해 UI 업데이트를 자동화할 수 있습니다.
단점으로는 간단한 화면에서는 오버엔지니어링이 될 수 있고 프로젝트 복잡도가 증가할 수 있습니다.
Kingfisher를 쓰면 참 간단해지는데... 그걸 도전과제에서 알려줬더라고요...