본문 바로가기

iOS/RxSwift

[Operators] Combining

RxSwift의 Combining 연산자 정리 🚌 🚌 🚌 ~

연산자 목차

- startWith

- concat

- merge

- combineLatest

- withLatestFrom

- reduce

- scan

startWith

Observable 맨 앞에 element를 추가해서 방출해주는 연산자입니다. 

 

let numbers = Observable.of(2,3,4)

numbers.startWith(1)
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

출력

// 1

// 2

// 3

// 4

 

concat

여러 Observable들을 순서대로 이어주는 연산자입니다. 

let first = Observable.of(1,2)
let second = Observable.of(3,4)
let third = Observable.of(5,6)

Observable.concat([first,second,third])
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

출력 

// 1

// 2

// 3

// 4

// 5

// 6

merge 

concat과 다르게 마블 다이어그램에서 보는대로 각 observable에서 element가 방출되는 시점 순으로 합쳐주는 연산자입니다.

let left = PublishSubject<Int>()
let right = PublishSubject<Int>()
Observable.of(left.asObservable(),right.asObservable())
    .merge()
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

left.onNext(1)
left.onNext(5)
right.onNext(4)
right.onNext(2)
left.onNext(102)

출력

// 1

// 5

// 4

// 2

// 102

combineLatest

observable들을 합쳐주는데 각 observable에서 마지막 시점에 방출했던 element를 합쳐줍니다. 

마블다이어그램에서 1만 방출되었을 때는 합칠 수 없는 것을 알 수 있습니다. 합쳐서 방출할 수 있는 두 element가 생겼을 때, 1A, 2A, 2B...를 보면 알 수 있듯이 각 observable의 마지막에 방출한 element를 이용해 combine해줍니다.

let left = PublishSubject<Int>()
let right = PublishSubject<Int>()
Observable
    .combineLatest(left, right, resultSelector: {
        "\($0) \($1)"
    })
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

left.onNext(1)
left.onNext(5)
right.onNext(4)
right.onNext(2)
left.onNext(102)

출력

// 5 4

// 5 2

// 102 2

withLatestFrom

combineLatest는 각 observable이 방출되는 모든 시점에 방출이 되었다면, withLatestFrom은 한가지 obsevable이 방출되는 시점에만 합쳐서 방출해줍니다. 

이런 상황은 UI에서 검색할 때 많이 사용됩니다.

마블 다이어그램에서 첫번쨰 observable을 button, 두번째 observable을 textField라고 생각해보면,

textField를 칠때마다 검색해야하는 자동완성기능이 아니라면, 검색버튼을 눌러야 검색이 됩니다. 따라서 버튼을 누를 때 마지막 시점에 친 검색어를 넘겨줄 수 있습니다. 

let button = PublishSubject<Void>()
let textField = PublishSubject<String>()

let observable = button.withLatestFrom(textField)
observable.subscribe(onNext: {
    print($0)
}).disposed(by: disposeBag)

textField.onNext("Sw")
textField.onNext("Swif")
textField.onNext("Swift")
button.onNext(())
textField.onNext("Swift Good!")
button.onNext(())

출력

// Swift

// Swift Good!

reduce

일반 swift에도 있는 연산자입니다. 수학적 계산을 할 때 주로 사용합니다.

reduce((x,y) => x + y) 와 같이 쓰입니다. 

let observable = Observable.of(1,2,3)

// 1
observable
    .reduce(0, accumulator: +)
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

// 2
observable
    .reduce(0, accumulator: {
        summary, newValue in
        return summary + newValue
    })
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

출력 

// 6

// 6

1번과 2번 방법 모두 같은 답입니다. 2번 방법이 더 눈에 들어오지만, 1번 방법과 같이 간단하게 사용할 수 있습니다. 

scan

reduce와 정말 비슷하지만 한 가지 차이점은 매 시점마다 결과를 방출해줍니다. reduce는 연산의 마지막 결과만 보여줍니다.

아래 마블 다이어그램을 비교하면 그 차이점을 확실히 알 수 있습니다.

scan vs reduce

let observable = Observable.of(1,2,3)
observable
    .scan(0, accumulator: +)
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

출력

// 1

// 3

// 6

 

출처

- https://reactivex.io/documentation/operators.html

- https://www.udemy.com/course/mastering-rxswift-in-ios/learn/lecture/13858552#overview

'iOS > RxSwift' 카테고리의 다른 글

[Operators] Transforming  (0) 2022.01.30
[Operators] Filtering  (0) 2022.01.30
[Observables] 개념  (0) 2021.05.14