๋ฐฉ์ถ๋๋ ๊ฐ์ ์ด๋ค ๋ณํ์ ์ฃผ์ด ๋ฐฉ์ถํ๋ ์คํผ๋ ์ดํฐ
#1
Observable.of(1, 2, 3)
.map({ (result: Int) -> Int in
result * 10
})
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
10
20
30
#2
Observable.of(1, 2, 3)
.map({ (result: Int) -> String in
"\(result)"
})
.subscribe(onNext:{
print("String: " + $0)
})
// onNext๊ฐ ์์ผ๋ฉด Event<Element> ๋ฅผ ๋ฐ๋๋ฐ ์ด๋ next, error ์ด๋ฐ ์ด๋ฒคํธ๋ฅผ ํธ๋ค๋ง ํ๊ธฐ ์ํจ์.
// .subscribe({
// print("String: " + $0)
// switch $0{
// case let .next(value):
// print(value)
// case let .error(error):
// print(error)
// default:
// print("finished")
// }
// })
.disposed(by: disposeBag)๊ฒฐ๊ณผ
String: 1
String: 2
String: 3
index์ value๋ฅผ ํ๋ผ๋ฏธํฐ๋ก ๋ฐ์์ ๊ฐ์ผ๋ก ๋ฆฌํด
Observable.of(1, 2, 3, 4, 5)
.enumerated()
.map({ (index: Int, value: Int) -> String in
index > 3 ? "\(value)" : "x"
})
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
x
x
x
x
5
์ด๋ฒคํธ๋ฅผ ๋ค๋ฅธ Observable๋ก ๋ณ๊ฒฝ
Observable ์ํ์ค์ element๋น ํ๊ฐ์ ์๋ก์ด Observable ์ํ์ค๋ฅผ ์์ฑํ๋ค. ์ด๋ ๊ฒ ์์ฑ๋ ์ฌ๋ฌ๊ฐ์ ์๋ก์ด ์ํ์ค๋ฅผ ํ๋์ ์ํ์ค๋ก ๋ง๋ค์ด ์ค๋ค.
Observer in Observer๋ฅผ ๋ค๋ฃฌ๋ค. (Observer ์์ Observer์ด๋ฉฐ, ๋ด๋ถ Observable์ inner Observable์ด๋ผ ํ๋ค. Observable์์ ์๋ Observable,)
#1
Observable.of(1, 2, 3)
.flatMap({ (result: Int) -> Observable<String> in
Observable.just("\(result)")
})
.subscribe(onNext:{ (result: String) in
print("String: " + result)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
String: 1
String: 2
String: 3
#2
๋น๋๊ธฐ ์ฒ๋ฆฌํ ๋ ๋ง์ด ์ฐ์
https://jcsoohwancho.github.io/2019-09-09-Rxswift%EC%97%B0%EC%82%B0%EC%9E%90-flatmap/
// 1์ด๋ง๋ค second๋ฅผ ๋ฐฉ์ถ
let timer1 = Observable<Int>
.interval(RxTimeInterval.seconds(1), scheduler: MainScheduler.instance)
.map({"o1: \($0)"})
// 2์ด๋ง๋ค second๋ฅผ ๋ฐฉ์ถ
let timer2 = Observable<Int>
.interval(RxTimeInterval.seconds(2), scheduler: MainScheduler.instance)
.map({"o2: \($0)"})
Observable.of(timer1, timer2)
.flatMap({ (emit: Observable<String>) -> Observable<String> in
emit
})
.subscribe({ (result: Event<String>) -> Void in
print(result)
switch result{
case let .next(value):
print(value)
default:
print("finished")
}
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
next(o1: 0)
o1: 0
next(o1: 1)
o1: 1
next(o2: 0)
o2: 0
next(o1: 2)
o1: 2
next(o1: 3)
o1: 3
next(o2: 1)
o2: 1
next(o1: 4)
o1: 4
next(o1: 5)
o1: 5
next(o2: 2)
o2: 2
map
Observable.of(timer1, timer2) .map({ (emit: Observable<String>) -> Observable<String> in emit }) .subscribe(onNext: { (result: Observable<String>) in print(result) }) .disposed(by: disposeBag)๊ฒฐ๊ณผ
RxSwift.(unknown context at $12071da78).Map<Swift.Int, Swift.String> RxSwift.(unknown context at $12071da78).Map<Swift.Int, Swift.String> next(o1: 0) o1: 0 next(o1: 1) o1: 1 next(o2: 0) o2: 0 next(o1: 2) o1: 2 next(o1: 3) o1: 3 next(o2: 1) o2: 1 next(o1: 4) o1: 4 next(o1: 5) o1: 5 next(o2: 2) o2: 2flatMap
Observable.of(timer1, timer2) .flatMap({ (emit: Observable<String>) -> Observable<String> in emit }) .subscribe(onNext: { (result: String) -> Void in print(result) }) .disposed(by: disposeBag)๊ฒฐ๊ณผ
o1: 0 o1: 1 o2: 0 o1: 2 o1: 3 o2: 1 o1: 4 o1: 5 o2: 2map์ Observable๊ฐ ๊ทธ๋๋ก ๋ฐ๋ ๋ฐ๋ฉด์: Observable --> subscribe({ Observable ... })
flatMap์ ์ธ๋ํํด์ ๋ฐ๊ณ ์์: Observable --> subscribe({ Element ... })
์ ์ด๋ฐ์ผ์ด ๋ฐ์ํ ๊น?
map
Observable.of(1, 2, 3) .map({ (emit: Int) -> Observable<Int> in Observable.just(emit) }) .subscribe(onNext:{ (result: Observable<Int>) in print(result) }) .disposed(by: disposeBag)flatMap
Observable.of(1, 2, 3) // return์ Observable<Int> ์ธ๋ฐ .flatMap({ (emit: Int) -> Observable<Int>/*๐*/ in Observable.just(emit) }) // subscribe์์ ๋ฐ๋ ๊ฐ์ upwrapping .subscribe(onNext:{ (result: Int)/*๐*/ in print(result) }) .disposed(by: disposeBag)map, flatMap์์์ return ํ์ ๋ง ๋ค๋ฅด๊ณ subscribe์์ ๋ฐ๋ ๊ฐ์ ํ์ ์ด ๊ฐ์.
flatMap์ ๊ฒฝ์ฐ Observable์ ๋ฆฌํดํ๋๋ฐ ๋ฐ๋ ๊ฐ์ unwrapping ํ ๊ฐ์. ์?
element๋น ์๋ก์ด Observable ์ํ์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๊ธฐ ๋๋ฌธ์ return๊ฐ์ด Observable์ด๋ค. ํ๋์ ์ํ์ค(subscribe)๋ฅผ ๋ง๋ค์๊ณ , ๊ฑฐ๊ธฐ์ ๋ํ value๋ฅผ ํธ๋ค๋งํ๋๊น ๋น์ฐํ unwrapping๋ ๊ฐ์ด์ด์ผ ํ๋ค.
(์๋ Answer๋ฅผ ๋ณด์)
https://rhammer.tistory.com/300 ์์ ๋ต์ ์ฐพ์ ์ ์์๋ค.
์ฐ์ flatMap์ด ์ด๋ค ๊ฒ์ธ์ง ๋ถํฐ ์์ธํ ๋ณผ ํ์๊ฐ ์๋ค.
๋ฌธ์์๋ flatMap์ ๋ค์๊ณผ ๊ฐ์ด ์ ์ํ๊ณ ์๋ค.
Projects each element of an observable sequence to an observable sequence and merges the resulting observable sequences into one observable sequence
Observable์ํ์ค์ element๋น ํ ๊ฐ์ ์๋ก์ด Observable ์ํ์ค๋ฅผ ์์ฑํ๋ค. ์ด๋ ๊ฒ ์์ฑ๋ ์ฌ๋ฌ๊ฐ์ ์๋ก์ด ์ํ์ค๋ฅผ ํ๋์ ์ํ์ค๋ก ํฉ์ณ์ค๋ค.
๊ธ๋ง ๋ดค์ ๋๋ ์ดํด๊ฐ ์์๊ฐ๋๋ฐ ๊ทธ๋ฆผ์ ๋ณด๋ฉด ์ ์ ์๋ค.
01 ์๋ฆฌ๋จผํธ๊ฐ flatMap์ ๋ง๋ ์๋ก์ด ์ํ์ค๊ฐ ์๊ฒผ๋ค. ์ด ์ํ์ค๋ 01์๋ฆฌ๋จผํธ์ vlaue์ ๋ํ ์ํ์ค๋ค.
์๋ก ์์ฑ๋ ์ํ์ค์ 10 ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๊ณ , ์ต์ข ์ํ์ค(์ ์ผ ํ๋จ ์ํ์ค)๋ก ์ ๋ฌ๋์๋ค.
์ฆ, 01์๋ฆฌ๋จผํธ์ value์ ๋ณ๋์ด ์์ผ๋ฉด, ์ด ์ํ์ค์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด๋ค.(์ค์)
02 ์๋ฆฌ๋จผํธ๊ฐ flatMap์ ๋ง๋ ์๋ก์ด ์ํ์ค๊ฐ ์๊ฒผ๋ค. ์ด ์ํ์ค๋ 02์๋ฆฌ๋จผํธ์ value์ ๋ํ ์ํ์ค๋ค.
์๋ก ์์ฑ๋ ์ํ์ค์ 20 ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๊ณ , ์ต์ข ์ํ์ค๋ก ์ ๋ฌ๋์๋ค.
์ฆ, 02์๋ฆฌ๋จผํธ์ value์ ๋ณ๋์ด ์์ผ๋ฉด, ์ด ์ํ์ค์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ ๊ฒ์ด๋ค.
01 ์๋ฆฌ๋จผํธ์ value์ ๋ณ๋์ด ์๊ฒผ๋ค. 1์์ 4๋ก ๋ฐ๋ ๊ฒ.(๊ทธ๋ฆผ์๋ ํ์ ์ํจ)
flatMap์ด ์์ฑํ ์ํ์ค ์ค 01์๋ฆฌ๋จผํธ์ ํด๋นํ๋ ์ํ์ค์ 40์ด๋ผ๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ฌ ์ต์ข ์ํ์ค๋ก ์ ๋ฌ๋์๋ค.
02 ์๋ฆฌ๋จผํธ์ value์ ๋ณ๋์ด ์๊ฒผ๋ค. 2์์ 5๋ก ๋ฐ๋ ๊ฒ.
flatMap์ด ์์ฑํ ์ํ์ค ์ค 02์๋ฆฌ๋จผํธ์ ํด๋นํ๋ ์ํ์ค์ 50์ด๋ผ๋ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ฌ ์ต์ข ์ํ์ค๋ก ์ ๋ฌ๋์๋ค.
flatMap์ ํ ์ํ์ค์ ์๋ฆฌ๋จผํธ๋ฅผ ์ ๋ฌ๋ฐ์ ์ด๋ฅผ ๋ณํํ ์๋ก์ด ์ํ์ค๋ฅผ ๋ง๋ค๊ณ (์๋ฆฌ๋จผํธ ํ๋ ๋น ์ํ์คํ๋ ์์ฑ) ์ด ์ํ์ค์์ ๋ฐ์ํ๋ ๋ชจ๋ ์ด๋ฒคํธ๋ฅผ ์ต์ข ์ํ์ค๋ก ์ ๋ฌํ๋ค.
์ฝ๋๋ฅผ ๋ณด์
struct Student{ var score: BehaviorSubject<Int> } // Student ํ์ ์ ๋ณ์ 2๊ฐ๋ฅผ ์์ฑ ryan์ 80, charlotte๋ 90์ผ๋ก ์ด๊ธฐํ ๋์ด์๋ค. let ryan = Student(score: BehaviorSubject(value: 80)) var charlotte = Student(score: BehaviorSubject(value: 90)) let student = PublishSubject<Student>() // student์ ์ํ์ค๋ฅผ ๋ณํํ๋ค. student // Student ์์ Observable<Int>์ผ๋ก ๋ณํ .flatMap({ (element: Student) -> Observable<Int> in element.score }) .subscribe(onNext:{ (result: Int) in print(result) }) .disposed(by: disposeBag)๊ทธ๋ฆผ์ผ๋ก ๋ณด๋ฉด ์ด๋ ๋ค.
next ์ด๋ฒคํธ๋ฅผ ๋ฐ์ ์์ผ ์ด๋ค ๊ฒฐ๊ณผ๋ฅผ ๋ด๋์ง ๋ณด์
student.onNext(ryan) ryan.score.onNext(85) student.onNext(charlotte) charlotte.score.onNext(95) charlotte.score.onNext(100)๊ฒฐ๊ณผ
80 85 90 95 100๊ฒฐ๊ณผ๊ฐ ๊ทธ๋ ๊ฒ ์ค์ํ ๊ฑด ์๋๊ณ , ์ด๋ค ์ผ์ด ์ผ์ด๋ฌ๋์ง๊ฐ ์ค์ํ๋ค.
flatMap์ observable์ element๋ณํ๋ฅผ ๊ณ์ ๊ด์ฐฐํ๊ณ ์๋ค. (ryan์ score (Observable์ด๋ค.)์ next ์ด๋ฒคํธ๋ฅผ ๋ฐฉ์ถํ๋ฉด flatMap์ด ์์์ฐจ๋ฆฐ๋ค.)
๊ทธ๋ฆผ์ผ๋ก ๋ณด๋ฉด ์ด๋ ๋ค.
์ ์ฐ๋์ง์ ๋ํด ์์๋ณด๊ธฐ ์ํด map๊ณผ ๋น๊ตํด๋ณด๊ฒ ๋ค.
student .map({ (element: Student) -> Observable<Int> in element.score }) .subscribe(onNext:{ (result: Observable<Int>) in result.subscribe(onNext:{ print($0) }) .disposed(by: disposeBag) }) .disposed(by: disposeBag) student.onNext(ryan) ryan.score.onNext(85) student.onNext(charlotte) charlotte.score.onNext(95) charlotte.score.onNext(100)๊ฒฐ๊ณผ
80 85 90 95 100๊ฐ์ ๊ฒฐ๊ณผ๋ฅผ ๋ด๊ธฐ ์ํด์๋ subscribe์์ subscribe๋ฅผ ํ๋ ๋ ๋ง๋ค์ด์ผ ํ๋ค.
๊ฒฐ๊ตญ์๋ ์ด์ง๊ฑฐ๋ฆฌ(subscribe์์ subscribeํ๋ ๋ ๋ฃ๋ ๊ฑฐ)๋ฅผ ์ํ๋ ค๊ณ flatMap์ ์ด๋ค.
์ ๋ฆฌํ์๋ฉด
flatMap์ Observable์ํ์ค์ element๋น ํ๋์ ์๋ก์ด Observable ์ํ์ค๋ฅผ ์์ฑํ๋ค. ์ด๋ ๊ฒ ์์ฑ๋ ์ฌ๋ฌ๊ฐ์ ์๋ก์ด ์ํ์ค๋ฅผ ํ๋์ ์ํ์ค๋ก ํฉ์ณ์ค๋ค.
Observable.of(1, 2, 3) // element( result: Int )๋น ํ๋์ ์๋ก์ด Observable์ํ์ค( Observable<String> )์ ์์ฑ .flatMap({ (result: Int) -> Observable<String> in ... }) // ์ด๋ ๊ฒ ์์ฑ๋ ์ฌ๋ฌ๊ฐ์ ์ํ์ค๋ฅผ ํ๋์ ์ํ์ค( subscribe๋ก ํ๋์ ์ํ์ค )๋ก ํฉ์ณ์ค๋ค. .subscribe(onNext:{ (result: String) in ... }) .disposed(by: disposeBag)์์ Question #1 ์ ๋ํ ๋ต์ด ๋๋ค.
element๋น ์๋ก์ด Observable ์ํ์ค๋ฅผ ๋ง๋ค์ด์ผ ํ๊ธฐ ๋๋ฌธ์ return๊ฐ์ด Observable์ด๋ค. ํ๋์ ์ํ์ค(subscribe)๋ฅผ ๋ง๋ค์๊ณ , ๊ฑฐ๊ธฐ์ ๋ํ value๋ฅผ ํธ๋ค๋งํ๋๊น ๋น์ฐํ unwrapping๋ ๊ฐ์ด์ด์ผ ํ๋ค.
https://rhammer.tistory.com/303 ๋ฅผ ์ฐธ๊ณ ํ์.
๊ธฐ์กด ์ต์ ๋ฒ๋ธ์ด ๋์ํ๊ณ ์๋ ๋์ค์ ์๋ก์ด ์ต์ ๋ฒ๋ธ์ด ์ ๋ฌ๋๋ฉด ๊ธฐ์กด๊ฒ์ ๋๊ธฐ๊ฒ ๋๋ ๊ฒ์ ์ ์ธํ๊ณ ๋ flatMap๊ณผ ๋์์ด ๋๊ฐ์.
flatMapLatest๋ flatMap๊ณผ switchLatest๋๊ฐ๊ฐ ํฉ์ณ์ง ํํ์ด๋ค.
switchLatest๋ Observer in Observer ๋ฅผ ๋ค๋ฃฌ๋ค. ๊ฐ์ฅ ์ต๊ทผ์ ์ถ๊ฐ๋ ์ํ์ค์ inner Observable๋ง ๋๊ฒจ์ค๋ค.
์ฆ, switchLatest์ flatMap์ ํฉ์น flatMapLatest๋ ๊ฐ์ฅ ๋ง์ง๋ง์ผ๋ก ์ถ๊ฐ๋ ์ํ์ค์ inner Observable ์ด๋ฒคํธ๋ง subscribeํ๊ฒ ๋๋ค.
๊ทธ๋ฆผ์ ๋ณด๋ฉด ์๋์ ๊ฐ๋ค.
-
flatMap๊ณผ ๋ง์ฐฌ๊ฐ์ง๋ก 01 ์๋ฆฌ๋จผํธ์ value์ ํด๋นํ๋ ์ํ์ค๊ฐ ์๊ธด๋ค. 01์๋ฆฌ๋จผํธ์ ์ต์ด value์ธ 1์ 10์ ๊ณฑํ์ฌ ์ต์ข ์ํ์ค๋ก ์ ๋ฌ๋๋ค.
-
๋ง์ฐฌ๊ฐ์ง๋ก 02์๋ฆฌ๋จผํธ์ value์ ํด๋นํ๋ ์ํ์ค๊ฐ ์๊ธด๋ค. 02์๋ฆฌ๋จผํธ์ ์ต์ด value์ธ 2์ 10์ ๊ณฑํ์ฌ ์ต์ข ์ํ์ค๋ก 20์ด ์ ๋ฌ๋๋ค.
๊ทธ๋ฆฌ๊ณ 01์๋ฆฌ๋จผํธ์ value๊ฐ 3์ผ๋ก ๋ณ๊ฒฝ๋์๋ค. 01์ํ์ค์๋ 30์ด ์ ๋ฌ๋์๋ค.
ํ์ง๋ง ์ต์ข ์ํ์ค์๋ ์ ๋ฌ๋์ง ์๋๋ค. ๊ฐ์ฅ ๋ง์ง๋ง์ ์์ฑ๋ ์ํ์ค์ธ 02์ํ์ค๊ฐ ์๊ธฐ ๋๋ฌธ 01์ํ์ค๋ ์์ผ๋ก ๊ณ์ ๋ฌด์๋๋ค.
-
03์๋ฆฌ๋จผํธ์ ํด๋นํ๋ ์ํ์ค๊ฐ ์๊ธด๋ค. 03์๋ฆฌ๋จผํธ์ ์ต์ด value์ธ 4์ 10์ ๊ณฑํ์ฌ ์ต์ข ์ํ์ค๋ก 40์ด ์ ๋ฌ๋๋ค.
๊ทธ๋ฆฌ๊ณ 02์๋ฆฌ๋จผํธ์ value๊ฐ 5๋ก ๋ณ๊ฒฝ๋์๋ค. 02์ํ์ค์๋ 50์ด ์ ๋ฌ๋์๋ค.
ํ์ง๋ง ์ต์ข ์ํ์ค์๋ ์ ๋ฌ๋์ง ์๋๋ค. ๊ฐ์ฅ ๋ง์ง๋ง์ ์์ฑ๋ ์ํ์ค์ธ 03์ํ์ค๊ฐ ์๊ธฐ ๋๋ฌธ 02์ํ์ค๋ ์์ผ๋ก ๊ณ์ ๋ฌด์๋๋ค.
๊ทธ๋ฆฌ๊ณ 03์๋ฆฌ๋จผํธ์ value๊ฐ 6์ผ๋ก ๋ณ๊ฒฝ๋์๋ค. 03์ํ์ค์๋ 60์ด ์ ๋ฌ๋์๋ค.
์ต์ข ์ํ์ค์๋ 60์ด๋ผ๋ ๊ฐ์ด ์ ๋ฌ๋์๋ค. 03์ํ์ค๋ ๊ฐ์ฅ ๋ง์ง๋ง์ ์์ฑ๋ ์ํ์ค์ด๊ธฐ ๋๋ฌธ์ด๋ค.
๋คํธ์ํฌ ํต์ ์์ ๋ง์ด ์ฌ์ฉ๋จ. ์๋ฅผ ๋ค์ด ๊ฒ์์ด ์๋์์ฑ ๊ฐ์ด G๋ง ์ณค์ ๋ ๋์ค๋ ๊ฒ๊ณผ GO๋ฅผ ์ณค์ ๋ ๋์ค๋ ๊ฒ์ด ๋ค๋ฅด๋ฏ ์ฌ์ฉ์๊ฐ ๋ง์ง๋ง์ ์น ๋ฌธ์์ด์ ๋ํด์ ์๋์์ฑ์ ์์ผ์ฃผ๋ ๊ฒ๊ณผ ๊ฐ์ ๊ธฐ๋ฅ์ ๊ตฌํํ ์ ์๋ค. G์์ ์ด์ด์ง๋ ๋์์ด ๋๊ธฐ๊ณ ๋ง์ง๋ง์ ๋ฐฉ์ถ๋ GO๋ก ์ด์ด์ง๋ ๋์๋ง ์ด์์๋ ๊ฒ
#1
struct Student{
var score: BehaviorSubject<Int>
}
// Student ํ์
์ ๋ณ์ 2๊ฐ๋ฅผ ์์ฑ ryan์ 80, charlotte๋ 90์ผ๋ก ์ด๊ธฐํ ๋์ด์๋ค.
let ryan = Student(score: BehaviorSubject(value: 80))
let charlotte = Student(score: BehaviorSubject(value: 90))
let student = PublishSubject<Student>()
student
.flatMapLatest({ (element: Student) -> Observable<Int> in
element.score
})
.subscribe(onNext:{ (result: Int) in
print(result)
})
.disposed(by: disposeBag)
student.onNext(ryan)
ryan.score.onNext(85)
// ์ฌ๊ธฐ์๋ถํฐ๋ ryan ์ํ์ค๋ ๋ฌด์๋๋ค.
student.onNext(charlotte)
// ์๋ ๋๋ฝ๋จ
ryan.score.onNext(95)
charlotte.score.onNext(100)๊ฒฐ๊ณผ
80
85
90
100
์ ์ฝ๋๋ฅผ ๊ทธ๋ฆผ์ผ๋ก ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๊ฐ์ฅ ๋ง์ง๋ง์ ์์ฑ๋ ์ํ์ค๊ฐ charlotte ์ํ์ค์ด๊ธฐ ๋๋ฌธ์ ryan์ 95 ์๋ฆฌ๋จผํธ๋ ๋ฌด์๋๋ ๋ชจ์ต
- flatMapLatest๋ฅผ ์ด์ฉํด ์์ฒญํ ๊ฒฐ๊ณผ๋ฅผ ๋ฐ์์ ๋ค์ ์์ฒญํ๊ธฐ(์ฝ๋ฐฑํฌ ์์ ๊ธฐ)/๋์์ ์ฌ๋ฌ๊ฐ ์์ฒญํ๊ธฐ
- ๋คํธ์ํฌ ์์ฒญ์ single๊ณผ ๊ฐ์ด ์ฐ์
์กฐ๊ฑด์ ํด๋นํ๋ ๊ฐ๋ง ๋ฐฉ์ถ
#1
Observable.of(1, 2, 3, 4, 5)
.filter({ (element: Int) -> Bool in
element < 3
})
.subscribe(onNext:{ (result: Int) in
print(result)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
1
2
๋ช๊ฐ์ ์๋ฆฌ๋จผํธ๋ฅผ ๊ฐ์ ธ์ฌ์ง ์ ํด์ค๋ค.
#1
Observable.of(1, 2, 3, 4)
.take(2)
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
1
2
์กฐ๊ฑด์์ด false๊ฐ ๋๊ธฐ ์ ๊น์ง๋ ๋ฐฉ์ถํ๊ณ false๊ฐ ๋๋ฉด ๋ค๋ก๋ ๋ฌด์
#1
Observable.of(1, 2, 3, 4, 5)
.take(while: {
$0 != 5
})
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
1
2
3
4
์ด๋ค ๋ค๋ฅธ ์ต์ ๋ฒ๋ธ์ ์คํ์ด ์๊ธฐ์ ๊น์ง ๊ฐ์ ธ์ค๊ณ ๊ทธ ๋ค๋ก ์ข ๋ฃ
#1
let subject = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()
subject
.take(until: subject2)
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)
subject.onNext(1)
subject.onNext(2)
subject2.onNext(10)
subject.onNext(3)
subject2.onNext(20)
subject.onNext(4)๊ฒฐ๊ณผ
1
2
Observable ์ํ์ค ์์ ๊ฐ์ ์ถ๊ฐํด์ค๋ค.
#1
Observable.of(1, 2, 3, 4)
.startWith(0)
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
0
1
2
3
4
์ฐธ๊ณ : https://rhammer.tistory.com/309?category=649741
Observable ์ํ์ค๋ฅผ ์์์์ด ํฉ์ณ์ค๋ค. 1๋ฒ 2๋ฒ Observable์ด ์๋ค๊ณ ํ์ ๋ 1๋ฒ ์ํ์ค ๋ฐฉ์ถ ํ๊ณ 2๋ฒ ์ํ์ค ๋ฐฉ์ถ( ์ด๊ฑด concat()์ )์ด ์๋๋ผ ์ํ์ค์ ๋ํด ์์๊ฐ ์์ด ๊ทธ๋ฅ ํ๋ฆ๋๋ก ํฉ์ณ์ค๋ค.
#1
let left = Observable.of("0", "1")
let right = Observable.of("zero", "one")
// let source = Observable.of(left, right)
// ์ด๋ ๊ฒ ํด๋ ๋จ
// source.merge()
Observable.merge(left, right)
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ(์์๋ ๋จผ์ ์ค๋ ์ด๋ฒคํธ๋ถํฐ๋ผ ๊ทธ๋๋ง๋ค ๋ค๋ฅธ ๊ฒฐ๊ณผ๊ฐ ๋์จ๋ค.)
0
zero
1
one
merge์ ๋ํ ๋ช๊ฐ์ง ๊ท์น
- ๋ด๋ถ ์ํ์ค๊ฐ ์ข ๋ฃ๋๋ฉด merge ์ํ์ค๋ ์ข ๋ฃ๋จ
- ๋ด๋ถ ์ํ์ค๊ฐ complete๋๋ ์์ ์ ๋ชจ๋ ๋ ๋ฆฝ์
- ๋ง์ฝ ๋ด๋ถ ์ํ์ค์์ ์๋ฌ๊ฐ ๋ฐ์ํ๋ฉด ๊ทธ ์ฆ์ merge์ํ์ค๋ ์๋ฌ๋ฅผ ๋ฐ์์ํค๋ฉฐ ์ข ๋ฃ๋จ
merge(maxConcurrent:)
์์ ์์๋ 2๊ฐ์ ์ํ์ค๋ง ํฉ์ณค์ง๋ง 2๊ฐ ์ด์์ ์ํ์ค๋ฅผ ํฉ์น ์๋ ์๋ค.
merge(maxConcurrent:)์คํผ๋ ์ดํฐ๋ฅผ ์ฌ์ฉํ๋ฉด ๋๋ค. maxConcurrent๊ฐ์๋งํผ ํฉ์น๋ค.
๋ง์ฝ maxConcurrent๊ฐ ์์์ ํฉ์ณ์ง์ง ๋ชปํ ์ํ์ค๋ ํ์ ๋๊ธฐํ๋ค๊ฐ, ๋ด๋ถ ์ํ์ค ์ค ํ๋๊ฐ complete๋๋ฉด ํฉ์ณ์ง๋ค.
์ฐธ๊ณ : https://rhammer.tistory.com/349?category=649741
๊ฐ๊ธฐ ๋๊ฐ์ Observable์ ํฉ์ฑํ๋ค. ๋ค๋ง ์ฒซ๋ฒ์งธ Observable์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํด์ผ ์ง๋ง 2๊ฐ๋ฅผ ๋ฌถ์ด์ ์ต์ข ์ํ์ค๋ก ์ ๋ฌํ๋ค. ์ฒซ๋ฒ์งธ ์ด๋ฒคํธ๊ฐ ์๋ค๋ฉด ์ต์ข ์ํ์ค๋ก ์ ๋ฌx
#1
let inputNumber = PublishSubject<Int>()
let inputString = PublishSubject<String>()
inputNumber
.withLatestFrom(inputString){ (lhs: Int, rhs: String) -> String in
"\(lhs):\(rhs)"
}
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)
// ๋ฐฉ์ถx
inputNumber.onNext(1)
inputString.onNext("one")
// 2:one
inputNumber.onNext(2)
inputString.onNext("two")
inputString.onNext("three")
inputString.onNext("four")
// 3:four
inputNumber.onNext(3)
// 4:four
inputNumber.onNext(4)
// 5:four
inputNumber.onNext(5)๊ฒฐ๊ณผ
2:one
3:four
4:four
5:four
#2
ํน์ ํธ๋ฆฌ๊ฑฐ๊ฐ ๋ฐ์ํ์ ๋, ํน์ ์ํ์ ์ต์ ๊ฐ์ ์ป๊ณ ์ถ์ ๋ ์ฌ์ฉํ๋ฉด ์ข๋ค.
let button = PublishSubject<Void>()
let textField = PublishSubject<String>()
button
.withLatestFrom(textField)
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)
// textField์ ์
๋ ฅ์ค
textField.onNext("Par")
textField.onNext("Pari")
textField.onNext("Paris")
// ๋ค ์
๋ ฅํ๊ณ ๋ฒํผ์ ๋๋ฒ ํญ
button.onNext(())
button.onNext(())๊ฒฐ๊ณผ
Paris
Paris
์ฐธ๊ณ : https://rhammer.tistory.com/311?category=649741
2๊ฐ์ OBservable์ ๊ฐ๊ฐ์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ ๋ ์ต์ ์ด๋ฒคํธ๋ผ๋ฆฌ ๋ฌถ์ด์ ์ต์ข ์ํ์ค์ ์ ๋ฌํ๋ค.
๋ ์ํ์ค๊ฐ ๊ฐ๊ฐ ์ต์ด ์ด๋ฒคํธ๋ฅผ ๋ฐ์์์ผ์ผ๋ง ํฉ์ณ์ง ์ํ์ค์์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค.
#1
let left = PublishSubject<String>()
let right = PublishSubject<String>()
Observable
.combineLatest(left, right) { lastLeft, lastRight in
"\(lastLeft) \(lastRight)"
}
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)
print("> Sending a value to left")
left.onNext("Hello, ")
print("> Sending a value to right")
right.onNext("world")
print("> Sending another value to right")
right.onNext("RxSwift")
print("> Sending another value to left")
left.onNext("Have a good day,")๊ฒฐ๊ณผ
> Sending a value to left
> Sending a value to right
Hello, world
> Sending another value to right
Hello, RxSwift
> Sending another value to left
Have a good day, RxSwift
๊ทธ๋ฆผ์ผ๋ก ํํ์๋ฉด ์๋์ ๊ฐ๋ค.
#2
let choice: Observable<DateFormatter.Style> = Observable.of(.short, .long)
let dates = Observable.of(Date())
Observable.combineLatest(choice, dates){ (format: DateFormatter.Style, when: Date) -> String in
let formatter = DateFormatter()
formatter.dateStyle = format
return formatter.string(from: when)
}
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
2022/03/07
March 7, 2022
Reference
Rx์์๋ ์ฌ์ฉ์์ ์ก์ ์ด๋ ์ ์ํด์ค ๊ฒ์ ๋ฐ๋ผ observable์ด ๋ฐฉ์ถ๋๋ค. ์ด ๋ง์ ๋ง์ฝ ๋์๋ค๋ฐ์ ์ผ๋ก ์ฌ๋ฌ ์ก์ ์ ์ทจํ๋ฉด observable์ด ๋ฐ๋ฅ๋ฐ๋ฅ ๋ถ์ด์ ๋ฐฉ์ถ๋๋ค๋ ์๊ธฐ.
- ๋ฒํผ์ ์ฌ๋ฌ๋ฒ ํด๋ฆญํ์ ๋
- API ์ค๋ณต ํธ์ถ์ ๋ง์์ฃผ๋ ๋ณ๋ ์กฐ์น๋ฅผ ์ทจํด์ค์ผ ํ๋๋ฐ
debounce๋ throttle์ ์ฌ์ฉํ๋ค.
์ง์ ๋ ์๊ฐ๋์ Observable์ด ๋ด๋ณด๋ธ ์ฒซ๋ฒ์งธ ์๋ฆฌ๋จผํธ์๋ง์ง๋ง ์๋ฆฌ๋จผํธ(latest ์ ๋ฐ๋ผ ๋ค๋ฆ)๋ฅผ ๋ด๋ณด๋ด๋ Observable์ ๋ฐํํ๋ค. ์ด ์ฐ์ฐ์๋ DueTime๋ณด๋ค ์งง์ ์๊ฐ์ ๋๊ฐ์ ์์๊ฐ ๋ด๋ณด๋ด์ง์ง ์๋๋ก ํ๋ค. (์ฐธ๊ณ : ๋ฐฉ์ถํ๋ฉด throttle ํ์ด๋จธ ํ๋ฌ๊ฐ)
์ง์ ๋ ์๊ฐ์์ ์๋ง์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํด๋ 2๊ฐ ์ด์ ์์๊ฐ ๋ฐฉ์ถ๋์ง ์๋๋ค๋ ์๊ธฐ์
throttle์ ์ฌ๋ฌ ์์ฒญ์ค์์ ๊ฐ์ ๋ฑ ํ๋ฒ๋ง ๋ณด๋ผ ๋ ์ฌ์ฉํ๋ค. tableView infinity scroll์ ๋ง์ด ์ฌ์ฉ๋๋ค. ๋ฏธ์น๋ฏ์ด ์คํฌ๋กค๋ง ํ๋ฉด ์์ฒญ์ด ์ฌ๋ฌ๋ฒ ์ด๋ฃจ์ด ์ง ์ ์์ผ๋ ์์ฒญ์ด ํ๋ฒ ์ด๋ฃจ์ด์ง๋ฉด throttle๋ก ๋๋ ์ด๋ฅผ ์ค์ ์๋ํ์ง ์์ ์์ฒญ์ ๋ง์ ์ ์๋ค. ๋๋ button์๋ ์ฌ์ฉ๋๋๋ฐ ๋ฏธ์น๋ฏ์ด button์ ๋๋ฅด๋ฉด api call์ ์ฌ๋ฌ๋ฒ ํ ์๋ ์์ผ๋ throttle๋ก ๋ง๋๋ค. (chattering๋ฐ์์ delay ์ฃผ๋๊ฑฐ๋ ๋๊ฐ๋ค.)
#1
latest๊ฐ true์ธ ๊ฒฝ์ฐ
Observable<Int>
.interval(.seconds(2), scheduler: MainScheduler.instance)
.take(6)
.throttle(.seconds(5), scheduler: MainScheduler.instance)
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
0
2
5latest๊ฐ true์ธ ๊ฒฝ์ฐ ์ง์ ๋ ์๊ฐ์ด ์ง๋ ์ดํ ๋ง์ง๋ง์ ๋ฐฉ์ถ๋ ์์๋ ๋ฐฉ์ถํด์ค๋ค. ๋ฐ๋ผ์ throttle ์๊ฐ์ด 5์ด ํ๋ฌ๊ฐ์ ๋ 4์ด์ ๋ฐฉ์ถ๋ 2๊ฐ ๋ง์ง๋ง ์๋ฆฌ๋จผํธ์ด๋ฏ๋ก 2๊ฐ ๋ฐฉ์ถ๋๋ค. ๊ทธ๋ฆฌ๊ณ ๋ค์ throttle์ 0์ด๋ถํฐ ์ด๋ฅผ ์ผ๋ค. 5์ด๊ฐ ์ง๋๊ณ 10์ด์ ๋ฐฉ์ถ๋ 5 ์๋ฆฌ๋จผํธ๋ฅผ ๋ฐฉ์ถํ๋ค.
๊ทธ๋ฆผ์ผ๋ก ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
#2
latest๊ฐ false์ธ ๊ฒฝ์ฐ
Observable<Int>
.interval(.seconds(2), scheduler: MainScheduler.instance)
.take(6)
.throttle(.seconds(5), latest: false, scheduler: MainScheduler.instance)
.subscribe(onNext:{
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
0
3
latest๊ฐ false์ธ ๊ฒฝ์ฐ ์ง์ ๋ ์๊ฐ๋์์ ์ด๋ ํ ๊ฐ๋ ๋ฐฉ์ถํ์ง ์๋๋ค. true์ผ๋์๋ ๋ค๋ฅด๊ฒ ๋ง์ง๋ง์ ๋ฐฉ์ถ๋ ๊ฐ๋ ๋ฐฉ์ถํ์ง ์๋๋ค.
๊ทธ๋ฆผ์ผ๋ก ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์ง์ ๋ ์๊ฐ๊ฐ๊ฒฉ ๋ด์ ๋ง์ง๋ง ํ๋์ source ์ด๋ฒคํธ๋ฅผ ์ต์ข ์ํ์ค์ ๋ฐฉ์ถํ๋ค. source ์ด๋ฒคํธ๊ฐ ๋ฐฉ์ถ๋ ๋๋ง๋ค ํ์ด๋จธ๋ ์ด๊ธฐํ๋๋ค.
#1
Observable<Int>
.interval(.seconds(2), scheduler: MainScheduler.instance)
.take(3)
.debounce(.seconds(1), scheduler: MainScheduler.instance)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
0
1
2
์๊ฐ ๊ฐ์ ๋ณด๋ฉด 2์ด๋ง๋ค timer๊ฐ ๋ฐ์ํ๊ณ debounce ์์ 1์ด๋ก ์ค์ ํ๊ธฐ์ 1์ด ๋ด์ ๋ค๋ฅธ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ์ง ์์ผ๋ฏ๋ก 1์ด๋ค debounce๋ Observable์ ์ด๋ฒคํธ๊ฐ ๋ฐ์ํ๋ค.
๊ทธ๋ฆผ์ผ๋ก ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
๋ง์ฝ deobunce์ 2๋ณด๋ค ํฐ๊ฐ(interval์์ ์ค์ ํ ์๊ฐ๊ฐ๋ณด๋ค ํฐ๊ฐ)์ ์ค์ ํ๋ฉด ์๋ฌด๊ฒ๋ ๋ฐฉ์ถํ์ง ์๋๋ค.
Observable<Int>
.interval(.seconds(2), scheduler: MainScheduler.instance)
.take(3)
// ๋ง์ฝ deobunce์ 2๋ณด๋ค ํฐ๊ฐ์ ์ค์ ํ๋ฉด ์๋ฌด๊ฒ๋ ๋ฐฉ์ถํ์ง ์๋๋ค.
.debounce(.seconds(3), scheduler: MainScheduler.instance)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)๊ฒฐ๊ณผ
์ฐธ๊ณ : https://jusung.github.io/shareReplay/
share๋ ๋์ผํ ์ฌ๋ฌ Observable์ ๋ํด ํ๋์ ์ํ์ค๋ง ์์ฑํด์ค๋ค. ์ฆ, ๋ฆฌ์์ค ๋น์ฉ์ ์ค์ฌ์ค๋ค.
์ฐ์ share๋ฅผ ์ค๋ช ํ๊ธฐ ์ ์ Observable์ ํน์งํ๋๋ฅผ ๊ธฐ์ตํ์. Observable์ subscribe๊ฐ ํธ์ถ๋๊ธฐ ์ ๊น์ง๋ ์ํ์ค๋ฅผ ์์ฑํ์ง ์๋๋ค.
๋ค์ ์ฝ๋๋ share๋ฅผ ์ ์ฉํ์ง ์์ ์ฝ๋์ด๋ค.
class ViewController: UIViewController{
let disposeBag = DisposeBag()
@IBOutlet weak var label: UILabel!
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let rx = Observable.of(100).debug("##")
let result = button.rx.tap
.flatMap{rx}
// .share()
result
.map{$0>0}
.bind(to: button.rx.isHidden)
.disposed(by: disposeBag)
result
.map { "\($0)" }
.bind(to: label.rx.text)
.disposed(by: disposeBag)
}
}๊ฒฐ๊ณผ
2022-03-09 11:22:22.674: ## -> subscribed
2022-03-09 11:22:22.676: ## -> Event next(100)
2022-03-09 11:22:22.677: ## -> Event completed
2022-03-09 11:22:22.677: ## -> isDisposed
2022-03-09 11:22:22.677: ## -> subscribed
2022-03-09 11:22:22.677: ## -> Event next(100)
2022-03-09 11:22:22.677: ## -> Event completed
2022-03-09 11:22:22.678: ## -> isDisposed
๋ฌธ์ ๊ฐ ๋ญ๋๋ฉด ๋์ผํ ์ํ์ค๊ฐ subscribe ๊ฐฏ์๋งํผ ์์ฑ๋์๋ค. 2๊ฐ๋ ์ต์ข
๊ฒฐ๊ณผ๋ ๋ค๋ฅผ์ง ๋ชฐ๋ผ๋ observable์ ํตํด ๋์ผํ๊ฒ next(100)์ ๋ฐฉ์ถํ ๊ฐ์ ์ฌ์ฉํ๋ค. next(100)์ด ๋๋ฒ ๋ฐ์ํ๋ค. ์ฆ, ์ํ์ค๊ฐ 2๊ฐ๋ผ๋ ๋ป
๊ทธ๋ฆผ์ผ๋ก ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
์ฐธ๊ณ ๋ก bind(to:)๋ฅผ ์ ์ง ์๊ณ subscrbie{...} ๋ฅผ ์ ์๋๋ฐ bind(to:)๋ subscribe์ ๋ณ์นญ(alias)์ผ๋ก subscrbie๋ฅผ ํธ์ถํ ๊ฒ๊ณผ ๋์ผํ๋ค.
share๋ subscribeํ ๋๋ง๋ค ์๋ก์ด ์ํ์ค๊ฐ ์์ฑ๋์ง ์๊ณ , ํ๋์ ์ํ์ค์์ ๋ฐฉ์ถ๋๋ ์๋ฆฌ๋จผํธ๋ฅผ ๊ณต์ ํด ์ฌ์ฉํ ์ ์๋ค.
class ViewController: UIViewController{
let disposeBag = DisposeBag()
@IBOutlet weak var label: UILabel!
@IBOutlet weak var button: UIButton!
override func viewDidLoad() {
super.viewDidLoad()
let rx = Observable.of(100).debug("##")
let result = button.rx.tap
.flatMap{rx}
.share()
result
.map{$0>0}
.bind(to: button.rx.isHidden)
.disposed(by: disposeBag)
result
.map { "\($0)" }
.bind(to: label.rx.text)
.disposed(by: disposeBag)
}
}๊ฒฐ๊ณผ
๊ทธ๋ฆผ์ผ๋ก ๋ณด๋ฉด ๋ค์๊ณผ ๊ฐ๋ค.
share()๋ subscribe()๊ฐ ์ฒ์ ํธ์ถ๋ ๋ (Subscriptoinํ์๊ฐ 0 -> 1 ์ผ๋)๋ง Subscription์ ์์ฑํ๊ณ , ์ดํ ๋๋ฒ์งธ ์ธ๋ฒ์งธ๋ก subscribe()๊ฐ ํธ์ถ๋๋ฉด ์๋ก์ด Subscription์ ์์ฑํ๋ ๊ฒ ๋์ ์ด๋ฏธ ๋ง๋ค์ด์ง Subscription์ ์ดํ subscribe()๋ฅผ ํธ์ถํ ๊ณณ์ ๊ณต์ ํด ์ฌ์ฉํ๋ค.
๋ง์ฝ share()์ subscribe()ํ Subscription์ด ๋ชจ๋ disposed ๋๋ฉด share()๋ ๊ณต์ ํ๋ Subscription์ dispose ์ํจ๋ค.
์ดํ ๋ค๋ฅธ subscribe()๊ฐ ํธ์ถ๋๋ฉด share()๋ ์๋ก์ด Subscription์ ์์ฑํ๋ค. ๊ทธ๋ ๊ธฐ ๋๋ฌธ์ share()๋ completed ๋์ง ์๋ Observable์ ์ฌ์ฉํ๋ ๊ฒ์ด ์์ ํ๋ค. ํน์ ๊ณต์ ํ๋ ์ํ์ค๊ฐ completed ๋ ํ ์๋ก์ด Observable์ด ์์ฑ๋์ง ์๋๋ค๊ณ ํ์ ํ ๋ ์ฌ์ฉํด์ผํ๋ค.
์์ ๋ฅผ playground๊ฐ ์๋ xcodeproj ์์ ํ ์ด์ ๋ ์ด์ ๊ฐ์ ๋งฅ๋ฝ์ด๋ค playground์์ ์๋์ ๊ฐ์ ์ฝ๋๋ฅผ ์คํํ๋ฉด 2๋ฒ์งธ ์ํ์ค๊ฐ ์ํ๋๊ธฐ ์ ์ completed ๋๊ธฐ ๋๋ฌธ์ share ์์ ๋ฅผ ๋ณด์ฌ์ฃผ๊ธฐ์ ์ด๋ ค์์ด ์๋ค.
let observable = Observable.of(1) .debug("### ") .share() observable .map{ $0 * 2 } .subscribe(onNext:{ print($0) }) .disposed(by: disposeBag) observable .map{ $0 * 3 } .subscribe(onNext:{ print($0) }) .disposed(by: disposeBag)๊ฒฐ๊ณผ
2022-03-09 11:16:26.771: ### -> subscribed 2022-03-09 11:16:26.771: ### -> Event next(1) 2 2022-03-09 11:16:26.772: ### -> Event completed 2022-03-09 11:16:26.772: ### -> isDisposed 2022-03-09 11:16:26.814: ### -> subscribed 2022-03-09 11:16:26.815: ### -> Event next(1) 3 2022-03-09 11:16:26.815: ### -> Event completed 2022-03-09 11:16:26.815: ### -> isDisposed๋ฌผ๋ก ์ด๋ ๊ฒ ํด๋ ๋์ง๋ง ์์ ์ฒ์ ์์ ๊ฐ ๋ ์ง๊ด์ ์ด๋ค.
let observable = PublishSubject<Int>() let reulst = observable.debug().share() reulst .map{ $0 * 2 } .subscribe(onNext:{ print($0) }) .disposed(by: disposeBag) reulst .map{ $0 * 3 } .subscribe(onNext:{ print($0) }) .disposed(by: disposeBag) observable.onNext(1)๊ฒฐ๊ณผ
2022-03-09 11:30:59.207: OperatorPractice.playground:643 (__lldb_expr_183) -> subscribed 2022-03-09 11:30:59.207: OperatorPractice.playground:643 (__lldb_expr_183) -> Event next(1) 2 3










