jane1choi/TIL

[RxSwift] Combining Operators - CombineLatest, Zip, Concat

Closed this issue · 0 comments

CombineLatest

공식문서

when an item is emitted by either of two Observables, combine the latest item emitted by each Observable via a specified function and emit items based on the results of this function

→ 아이템이 두 Observable 중 어느 하나에 의해 방출되면 지정된 함수를 통해 각 Observable에서 방출된 가장 최신 아이템을 결합하고, 이 함수의 결과에 따라 아이템들을 방출합니다.

R1280x0-4

두 개의 시퀀스가 combineLatest를 만나 하나의 시퀀스가 되었습니다.
이 합쳐진 시퀀스는 서브 시퀀스 (위에 두 개)에서 이벤트가 발생할 때마다 이벤트를 발생시킵니다.
합쳐진 시퀀스는 두 서브 시퀀스의 element를 조합하여 새로운 element를 전달합니다.
이렇게만 봐서는 어떻게 쓰이는 지 잘모르겠으니.. 예제로 봅시다!

우선 두 개의 시퀀스를 준비하고,

let left = PublishSubject<String>() 
let right = PublishSubject<String>()

combineLatest operator를 이용하여 하나로 합쳐진 시퀀스를 만들어줍니다.

let observable = Observable
.combineLatest(left, right, resultSelector: { (lastLeft, lastRight) in 
"\(lastLeft) \(lastRight)" 
})

let disposable = observable.subscribe(onNext: { (string) in print(string) })

이벤트를 발생 시키고, 그 값을 onNext로 받아서 프린트로 찍어볼게요!

그리고, 마지막에 dispose 해줍니다.

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,")

disposable.dispose()

결과는?? 아래와 같이 나옵니다!

스크린샷 2022-04-25 오후 4 07 36

  1. 이 예제에서는 Observable으로 같은 타입의 시퀀스를 합쳤지만, 두 개의 서브 시퀀스가 서로 다른 타입이어도 combine이 가능합니다.
  • 예시코드

    let disposeBag = DisposeBag()
    
    let first = Observable.of(1, 2, 3, 4)
    let second = Observable.of("A", "B", "C")
    
    Observable.combineLatest(first, second)
        .subscribe(onNext: { print("\($0)" + $1) })
        .disposed(by: dispseBag)
    
    /* Prints:
    1A
    2A
    2B
    3B
    3C
    4C
    */
  1. 결과에서 볼 수 있듯, 두 시퀀스가 각각 최초 이벤트를 발생 시켜야만 합쳐진 시퀀스에서 이벤트가 발생합니다.

두 개의 시퀀스가 최초 이벤트를 발생 시키고 난 후라면, 두 개의 시퀀스 중 어느 하나가 이벤트를 방출할 때마다 각 시퀀스의 마지막 값을 뽑아서 합쳐주니까 이메일, 비밀번호 texfield가 변할 때마다 버튼을 enabled를 체크해야 할 때 사용할 수 있을 것 같습니다!

Zip

공식 문서에 보면, CombineLatestZip 연산자는 유사한 방식으로 작동하지만 차이점이 있다고 나와있습니다.
zip에 대해서도 간단하게 알아봅시다!

공식문서

combine the emissions of multiple Observables together via a specified function and emit single items for each combination based on the results of this function

→ zip 연산자는 지정된 함수를 통해 여러 Observable의 방출을 결합하고 이 함수의 결과를 기반으로 각 조합에 대해 단일 항목을 방출합니다.

R1280x0-5

combineLatest는 일단 두 시퀀스 모두에서 최초 이벤트가 발생하면, 그 이후에는 두 개의 시퀀스 중 어느 하나가 이벤트를 방출할 때마다 각 시퀀스의 마지막 값을 뽑아서 합쳐줍니다.

zip은 두 시퀀스 모두에서 항상 새로운 이벤트가 발생되어야 두 이벤트가 조합됩니다.

Concat

공식문서

emit the emissions from two or more Observables without interleaving them

→ 두 개 이상의 옵저버블에서 인터리빙(= 서로 간섭)하지 않고 방출합니다.

쉽게 얘기하자면, 두 시퀀스를 합친다! 단, 순서가 보장됩니다.
concat

Concat 연산자 는 여러 Observable의 출력을 연결하여 단일 Observable처럼 작동합니다. 첫 번째 Observable에서 내보낸 모든 항목은 두 번째 Observable에서 내보낸 항목보다 먼저 내보내집니다.

→ 동작: first subscribe 하고 complete 발생한후 second를 subscribe 합니다.

  • 예시코드
let first = Observable.of(1, 2, 3) 
let second = Observable.of(4, 5, 6) 

// 1
Observable.concat([first, second]).subscribe(onNext: { value in print(value) })

// 2
first.concat(second).subscribe(onNext: { value in print(value) })
// 1 2 3 4 5 6

1. Observable의 class 메소드를 사용하여 시퀀스를 생성한다.
2. Observable의 인스턴스 메소드를 사용하여 시퀀스를 생성한다.

사용법은 이렇게 두 가지가 있다고 합니다!

참고자료: https://rhammer.tistory.com/311, https://ios-development.tistory.com/177