[RxSwift] Combining Operators

Judy·2023년 3월 16일
0

RxSwift

목록 보기
5/6
post-thumbnail

fimuxd/RxSwift를 참고해 정리하는 글입니다 🙂


붙이기

1. startWith(_:)

Observable에서 항목을 방출하기 전에 지정된 항목 시퀀스를 방출

  • Observable 이벤트를 받기 전 지정된 값을 먼저 받고 싶을 때
let numbers = Observable.of(2, 3, 4)

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

// Prints: 1 -> 2 -> 3 -> 4

2. Observable.concat(_:)

두 개 이상의 Observable을 끼워놓지 않고 방출합니다.

  • 여러 Observable을 하나의 Observable처럼 작동하게 함
  • 첫 번째 Observable이 모두 방출한 후 두 번째 Observable이 방출됨
let first = Observable.of(1, 2, 3)
let second = Observable.of(4, 5, 6)

let observable = Observable.concat([first, second])

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

/* Prints:
1
2
3
4
5
6
*/
  • 첫 번째 콜렉션의 sequence의 각 요소들이 완료될 떄까지 구독하고, 이어서 다음 sequence를 같은 방법으로 구독
  • 내부의 observable의 어떤 부분에서 에러가 방출되면, concat된 observable도 에러를 방출하며 완전 종료
let germanCities = Observable.of("Berlin", "Münich", "Frankfurt")
let spanishCities = Observable.of("Madrid", "Barcelona", "Valencia")

let observable = germanCities.concat(spanishCities)
observable.subscribe(onNext: { print($0) })
  • Observable.concat과 똑같이 작동
  • 반드시 두 observable의 요소가 같은 타입일 때만 가능

3. concatMap(_:)

  • flatMap과 유사하지만 Observable을 병합하는 대신 연결
let sequences = ["Germany": Observable.of("Berlin", "Münich", "Frankfurt"),
									"Spain": Observable.of("Madrid", "Barcelona", "Valencia")]
        
Observable.of("Germany", "Spain")
	.concatMap({ country in
		sequences[country] ?? .empty()
	})
	.subscribe(onNext: {
		print($0)
	})

// Berlin
// Münich
// Frankfurt
// Madrid
// Barcelona
// Valencia

합치기

1. merge()

단일 Observable처럼 작동하도록 여러 Observable의 출력을 결합

  • 만약 어떤 sequence라도 에러를 방출하면 merge()는 즉시 에러를 방출하고 종료
  • 모든 내부 sequence가 종료되면 종료

2. merge(maxConcurrent:)

  • 합칠 수 있는 sequence의 수를 제한
  • limit에 도달하면 이후에 들어오는 observable을 대기열에 넣고 현재 sequence 중 하나가 완료되면 구독을 시작
  • 네트워크 요청이 많아질 때 리소스를 제한하거나 연결 수를 제한하기 위해 사용될 수 있다

요소 결합

1. combineLatest(,,resultSelector:)

각 Observable에서 방출된 최신 항목을 결합하고 이 함수의 결과에 따라 항목을 방출

Observable 중 하나가 항목을 방출하면 CombineLatest는 제공한 함수를 사용하여 다른 소스 Observable 각각에서 가장 최근에 방출된 항목을 결합하고 해당 함수에서 반환 값을 방출

  • 여러 TextField를 한번에 관찰해 값을 결합하거나, 여러 소스들의 상태들을 보는 작업에 사용
let left = PublishSubject<String>()
let right = PublishSubject<String>()

Observable
	.combineLatest(left, right, resultSelector: { lastLeft, lastRight in
		"\(lastLeft) \(lastRight)"
	})
	.subscribe(onNext: {
		print($0)
	}).disposed(by: disposeBag)
       
left.onNext("Hello,")
right.onNext("world")
right.onNext("RxSwift")
left.onNext("Have a good day,")

// Hello, world
// Hello, RxSwift
// Have a good day, RxSwift
  • sequence 요소의 타입이 같을 필요는 없다
  • 2개부터 8개까지의 observable sequence를 파라미터로 가질 수 있다

2. combineLatest([],resultSelector:)

  • array내의 최종 값들을 결합하는 형태
Observable
	.combineLatest([left, right]) { strings in
		strings.joined(separator: " ")
	}

3. zip

  • 두개의 Observable을 병합

  • Observable의 방출을 함께 결합하고 지정된 함수의 결과에 따라 단일 항목을 방출
  • 결합할 수 있는 값이 방출될 때까지 방출하지 않음
enum Weather {
	case cloudy
	case sunny
}
        
let left: Observable<Weather> = Observable.of(.sunny, .cloudy, .cloudy, .sunny)
let right = Observable.of("Lisbon", "Copenhagen", "London", "Madrid", "Vienna")
        
Observable.zip(left, right, resultSelector: { (weather, city) in
	return "It's \(weather) in \(city)"
})
.subscribe(onNext: {
	print($0)
})
.disposed(by: disposeBag)

// It's sunny in Lisbon
// It's cloudy in Copenhagen
// It's cloudy in London
// It's sunny in Madrid
  • 둘 중 하나의 observable이라도 완료되면, zip역시 완료된다.
  • combineLatest처럼 2 ~ 8개의 observable에 대한 조합을 제공할 수 있다

Triggers

1. withLatestFrom(_:)

  • CombineLatest와 유사하지만 단일 소스 Observable이 항목을 내보낼 때만 항목을 방출

  • 어떤 observable은 단순히 방아쇠 역할
let button = PublishSubject<Void>()
let textField = PublishSubject<String>()
        
button.withLatestFrom(textField)
	.subscribe(onNext: {
		print($0)
	})
	.disposed(by: disposeBag)
        
textField.onNext("Par")
button.onNext(())
textField.onNext("Pari")
textField.onNext("Paris")
button.onNext(())

// Par
// Paris

2. sample(_:)

  • 주기적인 시간 간격 내에 Observable이 내보낸 가장 최근 항목을 내보냅니다.
  • withLatestFrom(_:)과 거의 똑같이 작동하지만, 한 번만 방출

textField.sample(button)
	.subscribe(onNext: {
		print($0)
	})
	.disposed(by: disposeBag)
        
textField.onNext("Par")
textField.onNext("Pari")
textField.onNext("Paris")
button.onNext(())
button.onNext(())
// Paris
  • withLatestFrom(_:)데이터 observable을 파라미터로 받고, sample(_:)trigger observable을 파라미터로 받는다.

Switches

1. amb(_:)

둘 이상의 Observable이 주어지면 첫 번째로 방출 Observable에서만 모든 항목을 방출

  • 어떤 한 요소를 방출하는 것을 기다리다가 하나가 방출을 시작하면 나머지 Observable에 대해서는 구독을 중단
let left = PublishSubject<String>()
let right = PublishSubject<String>()

left.amb(right)
	.subscribe(onNext: { value in
		print(value)
	})
	.disposed(by: disposeBag)

left.onNext("Lisbon")
right.onNext("Copenhagen")
left.onNext("London")
left.onNext("Madrid")
right.onNext("Vienna")

// Lisbon
// London
// Madrid

2. switchLatest()

  • source observable로 들어온 마지막 sequence의 아이템만 구독

let one = PublishSubject<String>()
let two = PublishSubject<String>()
    
let source = PublishSubject<Observable<String>>()
        
source.switchLatest()
	.subscribe(onNext: {
		print($0)
	})
	.disposed(by: disposeBag)
        
source.onNext(one)
one.onNext("Some text from sequence one")
two.onNext("Some text from sequence two")
        
source.onNext(two)
two.onNext("More text from sequence two")
one.onNext("and also from sequence one")
        
source.onNext(one)
one.onNext("Nope. It's me, one!")

// Some text from sequence one
// More text from sequence two
// Nope. It's me, one!
  • observable의 마지막 값들을 매핑하여 구독하는 flatMapLatest(_:) 과 유사

sequence내의 요소들간 결합

1. reduce(::)

  • Observable이 내보낸 각 항목에 함수를 순차적으로 적용하고 최종 값을 내보냅니다.
  • reduce와 유사

source.reduce(0, accumulator: +)
	.subscribe(onNext: {
		print($0)
	})
	.disposed(by: disposeBag)
// 25
  • 제공된 초기값(예제에서는 0)부터 시작해서 source observable이 값을 방출할 때마다 그 값을 가공하고 완료되면 방출
source.reduce(0, accumulator: { summary, newValue in
		return summary + newValue
	})
	.subscribe(onNext: {
		print($0)
	})
	.disposed(by: disposeBag)
// 위 코드와 동일

2. scan(_:accumulator:)

Observable이 내보낸 각 항목에 함수를 순차적으로 적용하고 각 연속 값을 방출

let source = Observable.of(1, 3, 5, 7, 9)
        
source.scan(0, accumulator: +)
	.subscribe(onNext: {
		print($0)
	})
	.disposed(by: disposeBag)
// 1
// 4
// 9
// 16
// 25
  • reduce 와 비슷하지만 적용한 값을 계속 방출



reactivex.io-operators

profile
iOS Developer

0개의 댓글