[RxSwift] #9 Combining Operators
1. 앞에 붙이기
1. startWith(_: Item)
Observable sequence 맨 앞에 기존 Observable 의 type 과 같은 type 의 data 를 붙여준다.
현재 상태에 초기값을 붙여서 전달할 때 사용.
let numbers = Observable.of(2, 3, 4)
let observable = numbers.startsWith(1)
observable
.subscribe(onNext: { print($0) } )
2. concat(_:)
2개의 sequence 를 묶는다.
1. Observable.concat(seq, seq)
let first = Observable.of(1, 2, 3)
let second = Observable.of(4, 5, 6)
let observable = Observable.concat([first, second]) // 1 2 3 4 5 6
2. seq.concat(_: seq)
위와 같음. 이렇게도 쓸 수 있다.
let observable = first.concat(second)
3. concatMap(_: (seq) -> seq)
flatMap 과 비슷하지만, 순서를 보장한다.
먼저 구독하는 것의 Observable sequence 를 모두 방출한 다음,
그 다음에 구독하는 것의 Observable sequence 를 방출한다.
map 이니까 함수도 적용할 수 있음.
let sequences = [
"Germany" : Observable.of("Berlin", "Munich", "Frankfurt"),
"Spain" : Observable.of("Madrid", "Barcelona", "Valencia")
]
// Germany 를 먼저 구독하게 된다.
let observable = Observable.of("Germany", "Spain")
.concatMap({ country in
sequences[country] ?? Observable.empty()
})
2. 합치기 (merge)
1. seq.merge()
Observable Sequence 가 내려오는 Sequence 를 구독한다.
여러 Sequence 를 고대로 내려서 하나로 합친다고 생각하면 됨. (절대적인 순서)
2. merge(maxConcurrent: Observable 개수)
합칠 수 있는 Sequence 의 수를 제한.
maxConcurrent 개의 Observable Sequence 가 들어오고 또 Observable 이 들어오면,
대기열에 넣어놓고 현재 Sequence 중 하나가 완료되면 바로 구독을 시작.
많이 쓰진 않지만, 네트워크 요청이 많아질 때처럼 제한이 필요한 경우가 있다.
let source = Observable.of(left.asObservable(), right.asObservable())
let observable = source.merge()
3. 결합하기 (combine)
1. combineLatest(: seq, : seq, resultSelector: {(item, item) -> item})
각 Sequence 의 현재 시점 가장 마지막 것을 합친다.
어떻게 합칠지에 대한 함수를 resultSelector 에 넣어주면 된다.
일반적으로 tuple 로 합치는 경우가 많다.
let left = PublishSubject<String>()
let right = PublishSubject<String>()
let observable = Observable.combineLatest(left, right, resultSelector: { lastLeft, lastRight in
return "\(lastLeft) \(lastRight)"
})
2. combineLatest([seq] ,resultSelector:)
// 위와 같은 결과가 나온다. 인자를 배열로 전달 가능.
let observable = Observable.combineLatest([left, right], resultSelector: { strings in
strings.joined(separator: " ")
}
3. zip
각 Observable 의 같은 index 끼리 합친다.
남는건 버림 - 두 Sequence 중 하나라도 종료되면 zip 된 것도 종료.
4. Trigger
여러개의 Observable 로 부터 데이터를 받을 때,
어떤 Observable 은 정보를 주는게 아니라 그저 trigger 역할을 할 수 있다.
1. trigger.withLatestFrom(_: data)
button 을 누르면 textField 의 가장 마지막 것을 방출
let button = PublishSubject<Void>()
let textField = PublishSubject<String>()
let observable = button.withLatestFrom(textField)
// 버튼을 구독하는데, 버튼에서 뭐가 들어오면 textField 의 가장 마지막 것을 보내주는 것.
_ = observable.subscribe(onNext: { print($0) })
textField.onNext("Par")
textField.onNext("Pari")
textField.onNext("Paris")
button.onNext(()) // Paris
button.onNext(()) // Paris
2. data.sample(_: trigger)
withLatestFrom 과 비슷하게 작동하지만, trigger 가 되는 것은 여러번 해도 한번만 출력됨
let observable = textField.sample(button)
// 순서도 반대. textField 의 sample 값인 버튼
// textField 에 더이상 onNext 로 값이 넘어오지 않을 때
// button 에 onNext 가 여러개 가도 한번만 출력됨.
// textField 에 값이 더 넘어가면 출력 됨
textField.onNext("Par")
textField.onNext("Pari")
button.onNext(()) // Pari
textField.onNext("Paris")
button.onNext(()) // Paris
button.onNext(())
1과 2는 같은 역할을 하는 코드이지만 체이닝을 덜하는게 좋다.
// 1
// trigger 를 parameter 로 받음
let observable = textField.sample(button)
_ = observable
// 2
// data 를 parameter 로 받음
let observable2 = button.withLatestFrom(textField)
_ = observable2
.distinctUntilChanged()
5. Switches
1. seq.amb(_: seq)
ambiguous 모호한.
여러 sequence 중 어떤 것을 구독할지 선택할 수 있게 만든다.
먼저 이벤트를 방출하는 쪽을 방출하고, 여러 sequence 중 하나라도 complete 되면 completed.
let observable = left.amb(right)
// left, right 를 모두 구독하고 있다가 left right 중 event 를 먼저 방출하는 쪽만 구독
// 나머지는 구독 끊어버림
2. Observable<Observable>.switchLatest()
observable sequence 를 data 로 가지는 Observable 에서
어떤 Observable 이 내려오면 해당 Observable 을 구독하고 있다가,
다른 Observable 이 내려오면 다른 Observable 을 구독
해당 시점부터의 event 들만 emit
let one = PublishSubject<String>()
let two = PublishSubject<String>()
let three = PublishSubject<String>()
let source = PublishSubject<Observable<String>>()
let observable = source.switchLatest()
let disposable = observable.subscribe(onNext: { print($0) })
source.onNext(one) // one 을 구독
two.onNext("Some txt from two")
one.onNext("Some txt from one")
two.onNext("Some txt from two")
source.onNext(two) // two 를 구독
two.onNext("Some txt from two")
one.onNext("Some txt from one")
source.onNext(three) // three 를 구독
two.onNext("Why don't you see me?")
one.onNext("I'm alone, help me")
three.onNext("Hey~")
source.onNext(one)
one.onNext("asdf")
disposable.dispose()
6. sequence 내 요소들 간의 결합
1. reduce(_: 초기값, accumulator: 연산)
초기값에 accumulator 에 있는 연산을 쌓아준다.
앞의 Observable 이 종료되는 시점에 결과값만 방출하고 completed
2. scan(_: 초기값, accumulator: 연산)
reduce 처럼 쌓긴 하는데 연산 과정에서 나오는 단계별 결과값도 방출한다.
7. Chaellenge
zip 을 이용해서 원래 값, scan 해서 쌓은 총합을 둘 다 출력해보자.
let source = Observable.of(1,3,5,7,9)
let observable2 = source.scan(0, accumulator: { summary, newValue in
return summary + newValue
})
observable2.subscribe(onNext: { print($0) })
let newSequence = Observable.zip(source, observable2)
newSequence.subscribe(onNext: { print($0) })
Author And Source
이 문제에 관하여([RxSwift] #9 Combining Operators), 우리는 이곳에서 더 많은 자료를 발견하고 링크를 클릭하여 보았다 https://velog.io/@ddosang/RxSwift-9-Combining-Operators저자 귀속: 원작자 정보가 원작자 URL에 포함되어 있으며 저작권은 원작자 소유입니다.
우수한 개발자 콘텐츠 발견에 전념 (Collection and Share based on the CC Protocol.)