RxSwfit
Reactive eXension + Swift
๋น๋๊ธฐ ํ๋ก๊ทธ๋๋ฐ์ ์ง๊ด์ ์ผ๋ก ์์ฑํ ์ ์๋๋ก ๋์์ ์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ
RxSwift๋ ๊ตฌ๋
(Observe)์ ํด์ ๋ฐ์ดํฐ ๋ณํ์ ๋ฐ์ํ๊ธฐ ๋๋ฌธ์ ๋น๋๊ธฐ ์ฒ๋ฆฌ๋ฅผ ์ฝ๊ฒ ํ ์ ์๋๋ก ๋์์ ์ฃผ๋ ๋ผ์ด๋ธ๋ฌ๋ฆฌ์ด๋ค.
Observable & Observer
โท Observable์ ํตํด์ ์ด๋ฒคํธ ๊ฐ์ ๋ฐฉ์ถ(Emit)ํ ์ ์๊ณ , ์ด ๊ฐ์ ๊ตฌ๋
(Subscribe)ํ์ฌ ๊ด์ฐฐํ๊ณ ๋ฐ์ํ ์ ์๋ค.
โท ํ๋ ์ด์์ ๊ด์์ฐจ(Observer)๊ฐ ์ค์๊ฐ์ผ๋ก ๋ฐ์ดํฐ ๋ณํ์ ๋ฐ์ํ์ฌ ์ฒ๋ฆฌํ๋ค. (ex. UI ์
๋ฐ์ดํธ, ํด๋ฆญ ์ด๋ฒคํธ, ...)
→ Observable์ ๊ตฌ๋
ํ๊ณ ์๋ Observer
โท Observable์ 3๊ฐ์ง ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ ์ ์๋ค.
- onNext: ๋ค์ ๊ฐ์ ์ ๋ฌํ๋ ์ด๋ฒคํธ(์๋ก์ด ๊ฐ์ด ๋ฐฐ์ถ๋ ๋๋ง๋ค ํธ์ถ)
- onError: ๊ฐ ๋ฐฐ์ถ ๊ณผ์ ์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด error๋ฅผ ๋ฐฉ์ถํ๊ณ ์ข
๋ฃ์ํค๋ ์ด๋ฒคํธ(= disposed)
- onCompleted: ์ฑ๊ณตํ ๊ฒฝ์ฐ ์ด๋ฒคํธ ์ํ์ค๋ฅผ ์ข
๋ฃ์ํค๋ ์ด๋ฒคํธ(= disposed)
Observable LifeCycle
1. Observable ์์ฑ
2. Subscribe๋ฅผ ํ ์์ ๋ถํฐ Observable ์คํ
3. next๋ฅผ ํตํด ์ด๋ฒคํธ ๋ฐฉ์ถ
Observable ์์ฑ ๋ฐฉ๋ฒ
์ด๋ฒคํธ๊ฐ ์ ๋ฌ๋๋ ์์ ์ Observer๊ฐ Observable๋ฅผ ๊ตฌ๋
(subscribe)์ ํ ์ดํ ๋ถํฐ์ด๋ค.
Observable๋ฅผ ์์ฑํ๋ ๋ฐฉ๋ฒ์ 4๊ฐ์ง๊ฐ ์๋ค.
1. just
2. of
3. from
4. Create
just๋ ์ค์ง ํ๋์ ๊ฐ์ ๋ฐฉ์ถํ๋ Observable Sequence๋ฅผ ์์ฑํ๋ค.
let observable = Observable.just(1)
์ด๋ ๊ฒ ๋จ ํ๋์ ํญ๋ชฉ๋ง ํ๋ผ๋ฏธํฐ๋ก ๋๊ฒจ์ค ์ ์๋ค.
์ด ์ํ๋ก subscribe(๊ตฌ๋
)์ ํ๊ฒ ๋๋ฉด,
obaservable.subscribe { value in
print(value)
} onError: { error in
print(error)
} onCompleted: {
print("onCompleted")
} onDisposed: {
print("onDisposed")
}
.disposed(by: disposeBag)
// <์คํ ๊ฒฐ๊ณผ>
// 1
// onCompleted
// onDisposed
์ด๋ ๊ฒ 1์ ํ๋ฒ ๋ฐฉ์ถํ๊ณ , ๋ฐ๋ก complete → dispose ๋๋ค.
์ด๋ ๊ฒ ํ๋๋ง ๋ฐฉ์ถํ๊ธฐ ๋๋ฌธ์ ๋ง์ฝ ๋ฐฐ์ด์ just์ ๋ฃ์ ๊ฒฝ์ฐ์๋ ๋ฐฐ์ด ์์ฒด๋ฅผ ๋ฐฉ์ถํ๊ณ ์ข
๋ฃ๋๋ค.
of๋ 1๊ฐ ์ด์์ ํญ๋ชฉ์ ๋ฐฉ์ถํ๋ Observable Sequence๋ฅผ ์์ฑํ๋ค.
let observable = Observable.of(1, 2, 3) // 1๋ฒ
let observable = Observable.of([1, 2, 3]) // 2๋ฒ
1๋ฒ์ 1 → 2→ 3→ ์ข
๋ฃ!
2๋ฒ์ฒ๋ผ of์ ์ธ์๋ก ๋ฐฐ์ด์ ๋ฃ๊ฒ ๋๋ฉด,
[1, 2, 3] → ์ข
๋ฃ!
์ด๋ ๊ฒ ๋จ์ผ ์์๋ก ๋ฐฉ์ถํ๋ค.
of๋ ์ด๋ ๊ฒ ๋ฐฉ์ถํ๊ณ ์ถ์ ๋งํผ ํญ๋ชฉ์ ๋๊ธธ ์ ์๋ค. ๋จ, ํ์
์ ๋ชจ๋ ๋์ผํด์ผํ๋ค.
// 1๋ฒ
obaservable.subscribe { value in
print(value)
} onError: { error in
print(error)
} onCompleted: {
print("onCompleted")
} onDisposed: {
print("onDisposed")
}
.disposed(by: disposeBag)
// <์คํ ๊ฒฐ๊ณผ>
// 1
// 2
// 3
// onCompleted
// onDisposed
1๋ฒ์์ ๋๊ฒจ์ค 1, 2, 3์ ์์๋๋ก ๋ฐฉ์ถํ๊ณ dispose๋๋ค.
// 2๋ฒ
obaservable.subscribe { value in
print(value)
} onError: { error in
print(error)
} onCompleted: {
print("onCompleted")
} onDisposed: {
print("onDisposed")
}
.disposed(by: disposeBag)
// <์คํ ๊ฒฐ๊ณผ>
// [1, 2, 3]
// onCompleted
// onDisposed
์ด๋ ๊ฒ 2๋ฒ์ฒ๋ผ ๋ฐฐ์ด์ ๋ฃ์ ๊ฒฝ์ฐ์๋
ํ๋ผ๋ฏธํฐ ํ๋๋ฅผ ํญ๋ชฉ์ผ๋ก ์ทจ๊ธํ๊ธฐ ๋๋ฌธ์ just์ฒ๋ผ ๋ฐฐ์ด์ ํ๋์ ํญ๋ชฉ์ผ๋ก ๋ฐฉ์ถํ๋ค
from์ ๋ฐฐ์ด์ ๊ฐ ์์๋ค์ ์์๋๋ก Observable Sequence๋ฅผ ์์ฑํ๋ค.
let observable3 = Observable.from([1, 2, 3])
from์ ๊ฐ๊ฐ์ ๊ฐ๋ค์ ๋ฐ์ ์ ์๊ณ , ์ค์ง ๋ฐฐ์ด๋ง ๋ฐ์ ์ ์๋ค.
obaservable.subscribe { value in
print(value)
} onError: { error in
print(error)
} onCompleted: {
print("onCompleted")
} onDisposed: {
print("onDisposed")
}
.disposed(by: disposeBag)
// <์คํ ๊ฒฐ๊ณผ>
// 1
// 2
// 3
// onCompleted
// onDisposed
์ด๋ ๊ฒ ํ๋ผ๋ฏธํฐ๋ก ๋ณด๋ธ ๋ฐฐ์ด์ ์์๋ค์ ์์๋๋ก ํ๋์ฉ ๋ฐฉ์ถํ๋ค.
์ ๋ฆฌํด๋ณด๋ฉด,
Observable๋ฅผ ๊ตฌ๋
ํ ์์ ๋ถํฐ ํ๋ผ๋ฏธํฐ๋ก ์ ๋ฌํ ํญ๋ชฉ๋ค์ด ์์๋๋ก ๋ฐฉ์ถ๋๊ณ , ์ด ๊ณผ์ ์ด ๋๋๋ฉด complete๊ฐ ๋ถ๋ฆฌ๋ฉด์ dispose๋๋ค.
of๋ Observable ๋ฐฐ์ด์ ๋ง๋ค๊ณ ! from์ ๋ฐฐ์ด์ ๊ฐ ์์๋ค์ Observable๋ก ๋ง๋ ๋ค.
ํ์
์ผ๋ก ๋ณด๋ฉด, of๋ Observable<[Int]>, from์ Observable<Int> ์ด๋ค.
๋ง์ง๋ง์ผ๋ก
create๋ ํ๋ผ๋ฏธํฐ๋ก Observer๋ฅผ ๋งค๊ฐ๋ณ์๋ก ๋ฐ๋ ํด๋ก์ ๋ฅผ ์ ๋ฌ๋ฐ๋ Observable Sequence๋ฅผ ์์ฑํ๋ค.
์์์ ์ธ๊ธํ๋ onNext, onError, onCompleted๋ฅผ ์ง์ ํธ์ถํ ์ ์๋ค. (onError, onCompleted 1๋ฒ๋ง ํธ์ถ ๊ฐ๋ฅ)
let obaservable = Observable<Int>.create { observer in
observer.onNext(1)
observer.onNext(2)
observer.onCompleted()
observer.onNext(3)
return Disposables.create()
}
create๋ just, of, from ๊ณผ ๋ค๋ฅด๊ฒ ์ด๋ ๊ฒ ํด๋ก์ ๋ฅผ ์ด์ฉํด์
onNext๋ฅผ ํตํด ์ด๋ค ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ ์ง,
์ธ์ onComplete, onError ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ ์ง๋ฅผ ์ง์ ํธ์ถํ ์ ์๋ค.
๋จ, onComplete, onError๊ฐ ํธ์ถ๋๋ฉด, dispose๊ฐ ๋์ด ์ข
๋ฃ๋๊ธฐ ๋๋ฌธ์ ์ดํ์๋ ์ด๋ค ๋ฉ์๋๋ ํธ์ถ๋์ง ์๋๋ค.
obaservable.subscribe { value in
print(value)
} onError: { error in
print(error)
} onCompleted: {
print("onCompleted")
} onDisposed: {
print("onDisposed")
}
.disposed(by: disposeBag)
// <์คํ ๊ฒฐ๊ณผ>
// 1
// 2
// onCompleted
// onDisposed
์คํ๊ฒฐ๊ณผ๋ฅผ ๋ณด๋ฉด, onCompleted ๋ค์์ ํธ์ถ๋ 3์ ๋ฐฉ์ถ๋์ง ์์ ๊ฒ์ ํ์ธํ ์ ์๋ค.
subscribe(๊ตฌ๋ )์ ํ ํ, dispose ํ๋ ๋ฐฉ๋ฒ
Observer๊ฐ Observable์ subscribe๋ฅผ ํตํด์ ์ด๋ฒคํธ๋ฅผ ๋ฐ๋๋ค.
๋ง์ฝ, ๋์ด์ Observable์ ๋ํ ์ด๋ฒคํธ๋ฅผ ๋ฐ๊ณ ์ถ์ง ์๋ค๋ฉด..?
์ด๋ ์ฌ์ฉํ๋ ๊ฒ์ด Disposable์ด๋ค.
Disposable์ subscribe ์ค์ธ ์ํฉ์์ ์ํ๋ ์๊ธฐ์ dispose(์ฒ๋ฆฌ)ํ ์ ์๋๋ก ๋์์ ์ฃผ๋ ์ญํ ์ ํ๋ค.
.dispose() ๋ฉ์๋๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค.
ํ์ง๋ง,
ํด๋์ค ๋ฉ๋ชจ๋ฆฌ๊ฐ ํด์ ๋๋ ์์ (deinit)์ Disposable์ด ๋๋๋ฐ, ํด๋์ค๊ฐ RootVC์ธ ๊ฒฝ์ฐ์๋ ๋ฉ๋ชจ๋ฆฌ์์ Disposable์ด ๋์ง ์๋๋ค.
์ด๋ฐ ๊ฒฝ์ฐ์๋ ์ง์ ํ์ํ ์์ ์ dispose๋ฅผ ํธ์ถํด ์ฃผ์ด์ผ ํ๋๋ฐ, ๊ตฌ๋
๊ฐ์ฒด๊ฐ ๋ง์์ง์๋ก ๊ด๋ฆฌํ๊ธฐ ํ๋ค์ด์ง๋ค.
์ด๋ฌํ ๋ฌธ์ ์ ๋ค์ด ์๊ธฐ ๋๋ฌธ์ DisposeBag์ ์ฌ์ฉํ๋ค.
(๊ณต์ ๋ฌธ์์๋ dispose() ์ง์ ํธ์ถ ๋ณด๋ค DisposeBag์ ์ฌ์ฉํ๋ผ๊ณ ์จ์์)
์ด๋ณด๋ค ๋ ์ข์ ๋ฐฉ๋ฒ์ด ์๋ค. ๋ฐ๋ก, DisposeBag์ ์ฌ์ฉํ๋ ๋ฐฉ๋ฒ์ด๋ค.
DisposeBag์ ๋ง๋ค์ด์ Disposable์ ๋ด์๋์๋ค๊ฐ ํ ๋ฒ์ ํธ์ถํ๋ ๊ฒ์ด๋ค.
let disposeBag = DisposeBag()
์ด๋ ๊ฒ disposeBag์ ๋ง๋ค์ด ๋๊ณ , ํด์ ๊ฐ ํ์ํ ์์ ์
.disposed(by: disposeBag)
์ด๋ ๊ฒ ํธ์ถํ๋ฉด ๋๋ค. (์ด๋ฏธ just, of ,from, create ์์์์ ์ฌ์ฉํ๊ณ ์์)
์ด๋ ๊ฒ DisposeBag์ ์ฌ์ฉํ๊ฒ ๋๋ฉด, ํ์ํ ์์ ์์ DisposeBag์ ์ธ์คํด์ค ์ด๊ธฐํ ๊ณผ์ ์ ํตํด์ ํ ๋ฒ์ ์ ๋ฆฌํ ์ ์๋ค.
'RxSwift' ์นดํ ๊ณ ๋ฆฌ์ ๋ค๋ฅธ ๊ธ
[RxSwift] BehaviorSubject, PublishSubject, ReplaySubject, AsyncSubject (0) | 2024.06.26 |
---|