2020. 5. 23. 03:31ㆍiOS/RxSwift
앞서 RxSwift 맛만보자!! 포스팅에서 비동기 작업을 도와주는 RxSwift의 간단한 동작을 보았습니다.
이제 이 RxSwift의 기능 2가지
- 비동기로 생기는 데이터를 Observable로 감싸서 리턴하는 방법
- Observable로 오는 데이터를 받아서 처리하는 방법
를 한번 자세히 알아보도록 하겠습니다.
먼저 원하는 데이터를 Observable로 감싸기 위해서는 Observable.create()를 호출해주어야 합니다. 그리고 우리는 이제 이 Obervable로 감싼 데이터를 리턴해 주도록 하겠습니다.
func downloadJson(_ url: String) -> Observable<String?>{
//1. 비동기로 생기는 데이터를 Observable로 감싸서 리턴하는 방법
return Observable.create() // Obervable 객체 생성
}
그리고 completion으로 원하는 데이터를 이 Obervable안에 emitter.onNext()의 인자로 넣어주게 됩니다. 그 다음 emitter.onCompleted()로 데이터 전송이 끝났음을 알려줍니다.
func downloadJson(_ url: String) -> Observable<String?>{
//1. 비동기로 생기는 데이터를 Observable로 감싸서 리턴하는 방법
return Observable.create() { emitter in // emitter를 통해 전송할 데이터를 관리할 수 있다.
emitter.onNext("Hello") // onNext 를 통해 데이터 전송
emitter.onNext("World")
emitter.onCompleted() // 데이터 전송이 끝남을 알려준다.
return Disposables.create()
}
}
이제 Observable로 오는 데이터를 받아서 처리해주는 방법입니다.subscribe 함수는 데이터가 받아와 질때 실행되는 함수 입니다.
// 2. Observable로 오는 데이터를 받아서 처리하는 방법
@IBAction func onLoad() {
self.editView.text = ""
setVisibleWithAnimation(activityIndicator, true)
downloadJson(MEMBER_LIST_URL)
.subscribe { event in
switch event {
case .next(let data):
self.editView.text = data
self.setVisibleWithAnimation(self.activityIndicator, false)
case .completed:
break
case .error(_):
break
}
}
}
이 subscribe는 이제 event 값으로 데이터 처리 방법을 분기처리를 시작합니다. .next로 앞서 전송한 데이터는 이 분기처리에서 .next(let data) 로 도달하게 됩니다.
앞서 next로 "Hello" 와 "World" 데이터를 전송해 주었습니다. 따라서 이 .next로 두번 도달하게 됩니다.
또한 이 이벤트에는 error와 completed가 있는데 앞서 emitter.completed()를 호출해 주지 않으면 데이터 전송이 끝나도 completed가 호출되지 않습니다. 따라서 이 이벤트는 클로져가 종료가 되지않고 남아있으면서 순환참조 문제가 발생할 수 있습니다. 따라서 데이터 전송이 끝났을 때 completed를 호출해주어야 합니다.
이제 이런 이벤트 처리를 URL Session으로 직접 사용해 보면서 적용시켜 보겠습니다.
func downloadJson(_ url: String) -> Observable<String?>{
return Observable.create() { emitter in
let url = URL(string: url)!
let task = URLSession.shared.dataTask(with: url) { (data, _, err) in
guard err == nil else {
emitter.onError(err!) // 에러가 난다면 .onError()를 호출
return
}
if let dat = data, let json = String(data: dat, encoding: .utf8) {
emitter.onNext(json) // 데이터를 잘 받아와진 경우엔 .onNext()를 호출
}
emitter.onCompleted() // 데이터 전송이 완료되면 .onCompleted() 호출
}
task.resume()
return Disposables.create() { // 이 객체는 이 Observable로 처리하는 작업을 중단 시킬수 있는 객체이다.
task.cancel() // 따라서 이 작업이 중단될 경우 URLSession 작업 또한 중지시킨다.
}
}
}
이렇듯 Observable은 하나의 생명주기를 가지게 됩니다.
1. Create 2. Subscribe 3. onNext 4. onCompleted / onError 5. Disposed
Create가 된다고 해서 데이터를 받아오기 시작하지 않으며 Subscribe에서 데이터를 받아오는 작업이 실행됩니다. 데이터를 전달해 주기 위해선 onNext를 통해 전달할 수 있고 전달 결과에 따라 onCompleted 또는 onError 로 처리가 됩니다.그리고 모든 작업이 완료되거나 정지시킬 경우 해당 Observable은 Disposed 상태가 됩니다.
이렇게 Disposed 상태가 되면 다시 실행시킬 수 없고, subscribe 함수를 다시 호출하여 데이터를 받아오는 작업을 실행시킬 수 있습니다.
@IBAction func onLoad() {
self.editView.text = ""
setVisibleWithAnimation(activityIndicator, true)
let disp = downloadJson(MEMBER_LIST_URL)
.subscribe { event in
switch event {
case .next(let data):
DispatchQueue.main.async {
// 앞서 URLSession을 통해 completion을 넘겨주었기 때문에 해당 작업 또한 URLSession 쓰레드에서 작업이 실행된다.
// 따라서 main 쓰레드로 UI 변경 작업을 해주어야 한다.
self.editView.text = data
self.setVisibleWithAnimation(self.activityIndicator, false)
}
case .completed:
print("completed")
break
case .error(_):
break
}
}
//disp.dispose() subscribe를 통해 수행되는 작업을 직접 중지시키는 함수
}
}
추가적으로 이러한 과정을 print 해주는 함수가 있습니다. 바로 debug()함수 입니다.
@IBAction func onLoad() {
self.editView.text = ""
setVisibleWithAnimation(activityIndicator, true)
let disp = downloadJson(MEMBER_LIST_URL)
.debug() //
.subscribe { event in
switch event {
case .next(let data):
break
case .completed:
break
case .error(_):
break
}
}
}
}
이렇게 create와 subscribe 사이에 debug() 함수를 호출해주면 다음과 같은 데이터가 콘솔창에 뜨게 됩니다.
2020-05-23 03:23:26.082: ViewController.swift:80 (onLoad()) -> subscribed
2020-05-23 03:23:27.086: ViewController.swift:80 (onLoad()) -> Event next(Optional("받아오는 데이터"))
2020-05-23 03:23:27.135: ViewController.swift:80 (onLoad()) -> Event completed
completed
2020-05-23 03:23:27.135: ViewController.swift:80 (onLoad()) -> isDisposed
이렇게 Observable 객체가 어떻게 사용이 되는지 이 데이터는 어떠한 생명 주기를 갖는지 알아보았습니다. 복잡한 구조를 갖고 있지만 하나씩 코드를 직접 처보면서 보다보면 충분히 이해가 가리라 생각됩니다 !!
'iOS > RxSwift' 카테고리의 다른 글
RxSwift 대망의 마지막 편..1 (0) | 2020.08.14 |
---|---|
RxSwift, 이제 드디어 뭐 좀 만들어 보자 !!!! (0) | 2020.06.27 |
RxSwift 4번째, Disposable에 대해 알아보쟈 (0) | 2020.06.13 |
RxSwift Operator에 대해서 알아보자 3탄 !! (0) | 2020.05.31 |
RxSwift 맛만 보자 !!! (0) | 2020.05.15 |