우선 RxSwift는 Return을 통해 데이터를 가지고 온다.
Rxswift를 사용하기 전에는 Alamofire으로 통신하는 경우 @escaping을 통해 데이터를 viewModel로 가져온 뒤
같은 방법으로 View로 데이터를 전달하였다.
해당 방법을 사용하면 코드가 복잡해지고 직관적이지 못하다는 단점이 있다.
(저는 그렇더라고요..ㅎ)
그래서!
우선 먼저 전체적인 흐름을 설명하자면
- Alamofire post 통신을 한 후 Observable을 이용하여 ViewModel 데이터를 가져온다.
- 가져온 데이터를 다시 Alamofire get 통신을 한 후 Observable을 이용하여 ViewModel 데이터를 가져온다.
- ViewModel로 가져온 데이터를 Observable을 이용하여 View로 보낸다.
□ ViewModel
class RxViewModel{
let disposeBag = DisposeBag()
func binding() -> Observable<Model>{
return Observable<Model>.create(){ observer in
RxService.escape.postData()
.subscribe(onNext: { data in
RxService.escape.getData(id: data).subscribe(onNext: { info in
print(info)
observer.onNext(info)
})
.disposed(by: self.disposeBag)
})
.disposed(by: self.disposeBag)
return Disposables.create()
}
}
}
→ Return으로 Observable로 하면 데이터를 비동기적으로 처리하여 view에 보낼 수 있다.
→ RxService.escape.postData()를 통해 아래 post 통신을 실행한다.
→ post 통신을 실행한 뒤 observable로 전달받은 데이터를 subscribe 하여 받는다.
→ 받은 데이터를 다시 Alamofire get 통신을 한다.
→ 같은 방법으로 진행한다.
□ Alamofire post 통신
func postData() -> Observable<Int>{
let url = "http://\(self.localhost)/api/members"
let body = ["githubId" : "HJ39"]
return Observable<Int>.create(){ observer in
AF.request(url,
method: .post,
parameters: body,
encoding: JSONEncoding.default,
headers: ["Content-type": "application/json"])
.validate(statusCode: 200..<201)
.responseDecodable(of: Int.self) { response in
switch response.result{
case .success(let data):
observer.onNext(data)
case .failure(let error):
print(error)
}
}
return Disposables.create()
}
}
→ url의 localhost는 서버와 연결하기 위해 서버의 ip를 넣으면 된다.
→ ViewModel에서 해당 함수를 실행하면 네트워크 통신 후 받은 데이터를 전달하게 된다.
→ Observable <Int>. create()를 통해 Observable을 생성한다. (인자로 escaping closure가 전달된다.)
→ Disposables를 통해 위에서 생성한 Observable을 메모리 상에서 삭제한다.
□ Alamofire get 통신
func getData(id:Int) -> Observable<Model>{
let url = "http://\(self.localhost)/api/members/\(id)"
return Observable<Model>.create(){ observe in
AF.request(url,
method: .get,
headers: ["Content-type": "application/json"])
.validate(statusCode: 200..<201)
.responseDecodable(of: DecodingModel.self) { response in
switch response.result{
case .success(let data):
observe.onNext(Model(id: data.id ?? 0,
name: data.name ?? "unknown",
githubId: data.githubId ?? "",
commits: data.commits ?? 0,
tier: data.tier ?? "",
authStep: data.authStep ?? "",
profileImage: data.profileImage ?? "",
rank: data.rank ?? 0,
tokenAmount: data.tokenAmount ?? 0))
case .failure(let error):
print(error)
}
}
return Disposables.create()
}
}
→ post통신과 크게 다른 점이 없다.
□ ViewController
class ViewController: UIViewController {
@IBOutlet weak var lablel1: UILabel!
let rxViewModel = RxViewModel()
let dispoesBag = DisposeBag()
override func viewDidLoad() {
super.viewDidLoad()
bindingData()
}
func bindingData(){
rxViewModel.binding().subscribe(onNext: { info in
guard let data = info.githubId else {return}
self.lablel1.text = "\(data)"
})
.disposed(by: dispoesBag)
}
}
→ bindingData()를 실행한 후 데이터가 들어오면 리턴되어 lablel1이 변경되게 했다.
MVVM 패턴 적용하기가 너무 어렵다..ㅠ
# 참고한 사이트
'iOS > RxSwift' 카테고리의 다른 글
RxSwift 사용 (0) | 2023.01.14 |
---|