[RxSwift] - Combining Operator(combineLatest, concat, merge, startWith, zip)

1. StartWith

: 소스 observable에서 item 방출을 시작하기 전에 특정 item을 방출합니다.

let yellow = Observable.of("a","b","c")

yellow
    .startWith("d")
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// 실행 시 다음을 출력합니다.
d
a
b
c

2. Concat

: 둘 이상의 observable을 서로 간섭(interleaving)하지 않고 배출합니다.

let classA = Observable.of("a","b","c")
let teacher = Observable.of("abc")

let line = Observable
    .concat([teacher,classA])

line
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// 실행 시 다음을 출력합니다.
abc
a
b
c

또는

teacher
    .concat(classA)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

startWith로 사용될 observable teacher에 concat으로 작성해주어도
아래와 같이 같은 결과를 출력합니다.

// 실행 시 다음을 출력합니다.
abc
a
b
c

+ concatMap

let children : [String: Observable<String>] = [
    "classA": Observable.of("a","b","c"),
    "classB": Observable.of("d","e","f")
]

Observable.of("classA","classB")
    .concatMap { className in
        children[className] ?? .empty()
    }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// 실행 시 다음을 출력합니다.
a
b
c
d
e
f

3. Merge

: 방출을 병합하여 여러 observable을 하나의 sequence로 만들어줍니다.

let a = Observable.from(["a","b","c","d"])
let b = Observable.from(["A","B","C","D"])

Observable.of(a,b)
    .merge()
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// 실행 시 다음을 출력합니다.
a
b
A
c
B
d
C
D

  • 규칙이나 순서 없이 도착하는 대로 출력합니다.

+ merge(maxConcurrent:)

let a = Observable.from(["a","b","c","d"])
let b = Observable.from(["A","B","C","D"])

Observable.of(a,b)
    .merge(maxConcurrent: 1)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)
  • merge를 통해서 한번에 받아낼 observable의 수를 의미합니다.
  • 지금은 1이기 때문에, observable a가 완료될 때까지 다른 observable을 받지 않기에, 순서대로 출력됩니다.

// 실행 시 다음을 출력합니다.
a
b
c
d
A
B
C
D

4. CombineLatest

: 두 observable에서 item이 방출될 때, 각 observable에서 가장 최근에 방출된 item을 작성된 함수에 따라 결합합니다.

let firstName = PublishSubject<String>()
let lastName = PublishSubject<String>()

let name = Observable
    .combineLatest(firstName,lastName) { first, last in
        first + last
    }

name
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)


firstName.onNext("peter")
lastName.onNext("john")
lastName.onNext("kim")
firstName.onNext("Michael")
lastName.onNext("Jackson")

// 실행 시 다음을 출력합니다.
peterjohn
peterkim
Michaelkim
MichaelJackson

5. Zip

: 여러 observable의 방출을 결합합니다.

그러나 combineLatest와 달리 짝을 맞춰 결합합니다.
따라서 만약 둘 중 하나의 observable이 먼저 끝나면
zip 전체가 끝나게 되어
다른 observable도 종료되어 짝이되지 못한 남은 item은 방출되지 않습니다.

enum result {
    case win
    case lose
}

let score = Observable<result>.of(.lose, .lose, .win, .win)
let player = Observable<String>.of("a","b","c","d","e","f","g")

let game = Observable
    .zip(score,player) { gameResult, gamePlayer in
        return "선수" + gamePlayer + " \(gameResult)"
    }

game
    .subscribe(onNext: {
        print($0)
    },onCompleted: {
        print("completed")
    })
    .disposed(by: disposeBag)

// 실행 시 다음을 출력합니다.
선수a lose
선수b lose
선수c win
선수d win
completed

  • player는 e,f,g가 남았지만, score가 종료되었기 때문에 모두 종료됩니다.

좋은 웹페이지 즐겨찾기