iOS/RxSwift

[RxSwift] Combining Operators

Chafle 2022. 11. 2. 18:33
반응형

startsWith

concat

merge

combineLatest

WithLatestFrom

Reduce

Scan

 


 

 

StartsWith

 

Sequence

2-4-3

다른 값으로 구성된 Sequence일 경우

startsWith를 사용할 경우 Sequence 첫번 째 위치에 삽입하는 것

 

let disposeBag = DisposeBag()

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

let observable = numbers.startWith(1)

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

 

 

2,3,4에 1이 추가된 것을 볼 수 있다.

 

 

반응형

 


 

 

Concat

 

두 개의 다른 Sequence가 있을 때

 

concat을 사용하면

두 개의 sequnce 값을 모두 포함하는 새로운 sequencer값을 도출한다.

 

let disposeBag = DisposeBag()

let sequence1 = Observable.of(1,2,3)
let sequence2 = Observable.of(4,5,6)

let observable = Observable.concat([sequence1,sequence2])
observable.subscribe(onNext: {
    print($0)
}).disposed(by: disposeBag)

 

 

 


Merge

 

 

시간을 기반으로 하는 연산자인데

 

관찰되는 시점이 다른 sequnce 2가지가 있을 때

 

 

 

  ----------------------------------------------------------------------------------->>>>>>
sequence1 1     2 3  
sequence2   4 5     6

 

merge sequence1, sequence2를 하게되면

관찰되는 순서 1,4,5,2,3,6순으로 병합하는 연산자이다.

 

let disposeBag = DisposeBag()

let sequence1 = PublishSubject<Int>()
let sequence2 = PublishSubject<Int>()

let source = Observable.of(sequence1.asObservable(),sequence2.asObservable())

let observable = source.merge()
observable.subscribe(onNext: {
    print($0)
}).disposed(by: disposeBag)

 

여기서 이제 event를 발생시키면

sequence1.onNext(6)
sequence1.onNext(3)
sequence2.onNext(2)
sequence2.onNext(1)
sequence1.onNext(13)

 

시간순으로 관찰이 될건데 6-3-2-1-13 순으로 발생이 될 것.

 

 


 

 

CombineLatest

 

  ----------------------------------------------------------------------------------->>>>>>
sequence1 1     2 3  
sequence2   4 5     6

두 개의 다른 sequence가 있을 때

CombineLatest를 수행하면

 

두 개의 sequence가 같이 출력될 때 까지 출력을 안하고 두 sequence값이 생길 때부터 출력이 되고,

event가 발생하면 바로 최신의 값으로 대체된다.

 

let disposeBag = DisposeBag()

let sequence1 = PublishSubject<Int>()
let sequence2 = PublishSubject<Int>()

let observable = Observable.combineLatest(sequence1,sequence2,resultSelector: { lastsequence1, lastsequence2 in
    "\(lastsequence1),\(lastsequence2)"
})

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

 

 

sequence1.onNext(45)
sequence1.onNext(20)

이렇게 하나의 sequence에만event를 발생시켜도 Combine하지 않는다

 


 

sequence1.onNext(45)
sequence1.onNext(20)
sequence2.onNext(1)

 

 

이렇게 두 sequence의 event발생이 생긴 시점부터 출력하기 시작하는데 event발생 시마다 업데이트 된다.

45는 아직 sequnce2의 evnet발생이 없으므로 출력이 안되고, 20의 값으로 교체되고, sequence2의 event발생이 시작한 시점부터 출력이 되는 것을 확인 할 수 있다.


 

 

sequence1.onNext(45)
sequence1.onNext(32)
sequence2.onNext(1)
sequence1.onNext(30)
sequence2.onNext(7)
sequence2.onNext(2)

 

 


 

withLatestFrom

 

 

sequence2의 event가 발생할 때만 sequence1의 event의 최근 값을 가져온다. 

특정 sequence나 컨트롤에서 최신 값을 가져와 병합이 가능하다.

즉 sequence2에 따라 sequence1의 값의 최근값을 가져온다.

 

 

 

let disposeBag = DisposeBag()

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

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

 

textField.onNext("I")
textField.onNext("I am")
textField.onNext("I am chassi")

 

여기까지는 출력 안된다. 다른 sequence가 발생하지 않았기 때문

textField.onNext("I")
textField.onNext("I am")
textField.onNext("I am chassi")
button.onNext(())

button의 event가 발생을 했을 때

최근의 값을 방출한다.

 

 

textField.onNext("I")
textField.onNext("I am")
textField.onNext("I am chassi")

button.onNext(())

textField.onNext("hi")
button.onNext(())

 

최근의 값을 계속 업데이트 해주는 것을 볼 수 있다.

 

 


 

Reduce

 

 

sequence를 취한 이후에 하나의 특정 값으로 줄이는 것

 

예를 들어 값이 1,2,3인 sequence가 있을 때 

reduce { 두 값을 더해라 }

연산을 거치면

6을 출력해 주는 것처럼 병합이 가능하다.

 

 

let disposeBag = DisposeBag()

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

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

 

reduce(a,b)

a는 초기값이고

b는 어떤 연산자로 값을 병합할지..

 

 

위 결과로 1,2,3을 더한 6의 값을 얻을 수 있다.

 

 

source.reduce(0, accumulator: {
    A,B in
    return A + B
}).subscribe(onNext: {
    print($0)
}).disposed(by: disposeBag)

 

위 방식으로 클로저로 따로 함수를 만들어줘도 같은 결과값을 도출 가능하다.

 

 


 

Scan

 

 

Scan은 reduce와 비슷하지만 업데이트 되는 값을 누계로 보여준다

 

let disposeBag = DisposeBag()

let source = Observable.of(1,2,3,7,8,8,9)

source.scan(0, accumulator: +)
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)

 

누적 합을 계속 업데이트 해주는 것을 확인할 수 있다.

반응형