# [RxSwift] Combining Operators & Triggers
# Prefixing and concatenating
# startWith(value)
- 기존 리스트에 첫 번째에 추가
example(of: "startWith") {
// 1
let numbers = Observable.of(2, 3, 4)
// 2
let observable = numbers.startWith(1)
_ = observable.subscribe(onNext: { value in
print(value)
// 1, 2, 3, 4
})
}
# concat([])
※ 단, Observable.contat()에 들어가는 것은 무조건 동일 타입이어야 함
example(of: "Observable.concat") {
// 1
let first = Observable.of(1, 2, 3)
let second = Observable.of(4, 5, 6)
// 2
let observable = Observable.concat([first, second])
observable.subscribe(onNext: { value in
print(value)
})
}
# merge
두 개의 Observable Sequence를 하나의 Observable Sequence로 합침
example(of: "merge") {
// 1
let left = PublishSubject<String>()
let right = PublishSubject<String>()
// 2
let source = Observable.of(left.asObservable(), right.asObservable())
// 3
let observable = source.merge()
let disposable = observable.subscribe(onNext: { value in
print(value)
})
// 4
var leftValues = ["Berlin", "Munich", "Frankfurt"]
var rightValues = ["Madrid", "Barcelona", "Valencia"]
repeat {
switch Bool.random() {
case true where !leftValues.isEmpty:
left.onNext("Left: " + leftValues.removeFirst())
case false where !rightValues.isEmpty:
right.onNext("Right: " + rightValues.removeFirst())
default:
break
}
} while !leftValues.isEmpty || !rightValues.isEmpty
// 5
left.onCompleted()
right.onCompleted()
}
/* prints
Left: Berlin
Right: Madrid
Left: Munich
Right: Barcelona
Left: Frankfurt
Right: Valencia
*/
# zip
example(of: "zip") {
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")
let observable = Observable.zip(left, right) { weather, city in
return "It's \(weather) in \(city)"
}
_ = observable.subscribe(onNext: { value in
print(value)
})
}
/* prints :
It's sunny in Lisbon
It's cloudy in Copenhagen
It's cloudy in London
It's sunny in Madrid
*/
# Triggers
특정 시점에 observable들을 받아들여야 하는 경우에 이용
# withLatestFrom
example(of: "withLatestFrom") {
// 1
let button = PublishSubject<Void>()
let textField = PublishSubject<String>()
// 2
let observable = button.withLatestFrom(textField)
_ = observable.subscribe(onNext: { value in
print(value)
})
// 3
textField.onNext("Par")
textField.onNext("Pari")
textField.onNext("Paris")
button.onNext(())
button.onNext(())
}
/*
Paris
Paris
*/
# sample
- withLatestFrom과 기능 동일, 단 1회성 emit
example(of: "sample") {
// 1
let button = PublishSubject<Void>()
let textField = PublishSubject<String>()
// 2
let observable = button.sample(textField)
_ = observable.subscribe(onNext: { value in
print(value)
})
// 3
textField.onNext("Par")
textField.onNext("Pari")
textField.onNext("Paris")
button.onNext(())
button.onNext(())
}
/*
Paris
*/
# switches
subscriber가 어떤 sequence의 이벤트를 수신할지 결정
# amb
ambiguous(모호한) : 먼저 온 sequence만 구독
server에서 대량의 데이터가 오는 경우 사용
example(of: "amb") {
let left = PublishSubject<String>()
let right = PublishSubject<String>()
// 1
let observable = left.amb(right)
let disposable = observable.subscribe(onNext: { value in
print(value)
})
// 2
left.onNext("Lisbon")
right.onNext("Copenhagen")
left.onNext("London")
left.onNext("Madrid")
right.onNext("Vienna")
left.onCompleted()
right.onCompleted()
}
/* print
Lisbon
London
Madrid
*/
# sequence내의 요소들간 결합
higher-order function에서의 reduce와 기능 동일
# reduce(:😃
example(of: "reduce") {
let source = Observable.of(1, 3, 5, 7, 9)
// 1
let observable = source.reduce(0, accumulator: +)
observable.subscribe(onNext: { print($0) } )
}
let observable2 = source.reduce(0, accumulator: { summary, newValue in
return summary + newValue
})
observable2.subscribe(onNext: { print($0) })
# scan(_:accumulator:)
- reduce(::)와 같이 작동하지만 리턴값이 Observable이며 하나의 값으로 나오는게 아니고 누적되며 emit
example(of: "scan") {
let source = Observable.of(1, 3, 5, 7, 9)
let observable = source.scan(0, accumulator: +)
observable.subscribe(onNext: { print($0) })
/* Prints:
1
4
9
16
25
*/
}