일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 | 29 |
30 | 31 |
- SwiftUI
- swipe
- struct
- LeetCode
- 개발후기
- API
- flatMap
- TMDB
- optional
- switch
- typecasting
- 폰트
- 프로그래머스
- FSCalendar
- RxSwift
- SF 폰트
- Lifecycle
- enum
- 회고록
- ios
- Crashlytics
- dfs
- Firebase
- Xcode
- http
- 알고리즘
- viewcontroller
- ios13
- Swift
- Realm
- Today
- Total
Jerry's Bakery
[RxSwift] Observable flatMap 사용법(API 호출 예제 포함) 본문
flatMap이란?
ReactiveX에 있는 설명에 따르면 Observable으로 방출된 항목을 다시 다른 Observable로 방출하는 것입니다.
자체적으로 Observable이 있거나, 다른 방식으로 Observable로 변환할 수 있는 Observable이 있을 때 유용하게 사용할 수 있습니다.
더 자세한 설명은 아래 링크를 참조해주시면 감사드리겠습니다.
ReactiveX - FlatMap operator
<!-- TODO: flatMapFirst, flatMapWithMaxConcurrency, selectSwitchFirst, selectWithMaxConcurrent https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/core/operators/flatmapfirst.md https://github.com/Reactive-Extensions/RxJS/blob/master/doc/api/co
reactivex.io
본 글에서는 flatMap을 사용하여 SearchBar입력값으로 API 호출을 진행하는 프로젝트를 진행해 보겠습니다.
프로젝트 링크는 아래와 같습니다.
GitHub - noh3310/FlatMapProject
Contribute to noh3310/FlatMapProject development by creating an account on GitHub.
github.com
APIManager
API를 호출하는 코드입니다.
RxAlamofire를 사용해 Observable<[Repos]>를 리턴하는 함수입니다.
func apiCall(_ str: String) -> Observable<[Repos]> {
let parameters: Parameters = [
"q": str
]
return RxAlamofire.requestData(.get, URL(string: "https://api.github.com/search/repositories")!, parameters: parameters)
.map { (response, data) in
do {
let decoder = JSONDecoder()
let result = try decoder.decode(ReposResult.self, from: data)
return result.items
} catch {
return []
}
}
}
ViewModel
ViewModel 클래스는 searchBar값을 바인딩하는 searchText변수와, API 결괏값을 담고 있는 result 값을 담고 있는 result 두 변수를 가지고 있습니다.
let searchText = BehaviorRelay<String>(value: "")
let result = PublishRelay<[Repos]>()
아래 코드에서 searchText의 값이 변경될 때 flatMap을 사용해 API를 호출합니다.
호출된 API는 Observable<[Repos]>를 리턴하고, 리턴된 Observable을 구독해 [Repos]를 result에 Accpet 합니다.
searchText
.flatMap { self.apiManager.apiCall($0) } // Observable<[Repos]> 리턴
.subscribe(onNext: { self.result.accept($0) })
.disposed(by: disposeBag)
View
searchBar의 입력값을 ViewModel의 searchText에 바인딩합니다.
searchBar.rx.text.orEmpty
.bind(to: viewModel.searchText)
.disposed(by: disposeBag)
viewModel의 result를 구독하고, 결괏값을 tableView에 바인딩합니다.
viewModel.result
.bind(to: tableView.rx.items(cellIdentifier: "cell")) { (indexPath, cellViewModel, cell) in
if #available(iOS 14.0, *) {
var config = cell.defaultContentConfiguration()
config.text = cellViewModel.fullName
cell.contentConfiguration = config
} else {
cell.textLabel?.text = cellViewModel.fullName
}
}
.disposed(by: disposeBag)