관찰 가능한 데이터를 새로운 시퀀스로 변형하는 operator이다.
여러 개의 항목들을 하나의 배열로 변환해주는 operator이다.
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5)
.toArray()
.subscribe({
print($0)
}).disposed(by: disposeBag)
// 실행결과
// success([1, 2, 3, 4, 5])
toArray()
의 반환 타입이 Single<[Element]>
인데, 그래서 subscribe에 onNext
가 없는 것 같다. 나중에 업데이트 된 것 같은데 더 알아봐야 할 듯
시퀀스의 각 항목들에 함수를 적용하는 함수. Swift의 map과 유사하다.
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5)
.map {
return $0 * 2
}.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
/* 실행 결과
2
4
6
8
10
*/
Observable에 의해 방출된 항목을 다시 Observable로 변형하고 방출된 항목을 다시 하나의 Observable로 평면화한다.
let disposeBag = DisposeBag()
struct Student {
var score: BehaviorRelay<Int>
}
let john = Student(score: BehaviorRelay(value: 75))
let mary = Student(score: BehaviorRelay(value: 95))
let student = PublishSubject<Student>()
.flatMap { $0.score.asObservable() }
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
student.onNext(john)
john.score.accept(100)
student.onNext(mary)
// 실행결과
// 75
// 100
// 95
john의 score 값을 변경하려면 같이 accept
메소드를 사용해야 한다.
위 예시처럼 내부에 있는 Observable을 변형하고 평면화할 때 유용하다고 한다.
Map은 단순한 값을 반환하지만 flatMap은 Observable을 반환하는 것이 가장 큰 차이인 것 같다. 아직은 둘의 차이점이 완전히 와닿지는 않음 ㅠ-ㅠ
let disposeBag = DisposeBag()
struct Student {
var score: BehaviorRelay<Int>
}
let john = Student(score: BehaviorRelay(value: 75))
let mary = Student(score: BehaviorRelay(value: 95))
let student = PublishSubject<Student>()
.flatMapLatest { $0.score.asObservable() }
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
student.onNext(john)
john.score.accept(100)
student.onNext(mary)
john.score.accept(45)
/* 실행 결과
75
100
95
*/
flatMap에서 발생하는 이벤트 중 가장 최신 이벤트만 관찰하고 싶을 때 사용하는 operator이다.
위 예시에서는 마지막으로 mary를 observe 하고 있기 때문에 john의 score 값을 바꿔도 이벤트가 무시되는 것을 볼 수 있다.
Observable의 항목들을 방출하기 전 특정 시퀀스를 먼저 방출한다.
let disposeBag = DisposeBag()
let numbers = Observable.of(2, 3, 4)
let observable = numbers.startWith(1)
observable.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
/* 실행 결과
1
2
3
4
*/
둘 이상의 Observable을 하나로 합쳐주는 Operator이다.
let disposeBag = DisposeBag()
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)
}).disposed(by: disposeBag)
/* 실행 결과
1
2
3
4
5
6
*/
여러 개의 Observable들을 하나로 합치는 operator이다. concat
operator와 달리 각 값들의 도착 시간을 기준으로 순서가 정해진다.
let disposeBag = DisposeBag()
let left = PublishSubject<Int>()
let right = PublishSubject<Int>()
let source = Observable.of(left.asObservable(), right.asObservable())
let observable = source.merge()
observable.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
left.onNext(5)
left.onNext(3)
right.onNext(2)
right.onNext(1)
left.onNext(99)
/* 실행 결과
5
3
2
1
99
*/
left
와 right
를 observe 하는 Observable을 만들고, 여기에 merge
operator를 적용한다.
두 Observable의 최신 항목들을 합쳐서 새로운 결과를 만드는 operator이다.
let disposeBag = DisposeBag()
let left = PublishSubject<Int>()
let right = PublishSubject<Int>()
let observable = Observable.combineLatest(left, right, resultSelector: {
lastLeft, lastRight in
"\(lastLeft) \(lastRight)"
})
let disposable = observable.subscribe(onNext: { value in
print(value)
})
left.onNext(45)
right.onNext(1)
left.onNext(30)
right.onNext(1)
right.onNext(2)
/* 실행 결과
45 1
30 1
30 1
30 2
*/
combineLast
operator는 resultSelector
라는 파라미터를 가진다!
source Observable을 다른 Observable들과 결합해서 새로운 observable을 만든다. source Observable에서 항목이 방출될 때만 다른 observable들의 최신 값들과 source observable의 값이 합쳐진다.
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("Sw")
textField.onNext("Swif")
textField.onNext("Swift")
button.onNext(())
button.onNext(())
/* 실행 결과
Swift
Swift
*/
위 예제에서는 button
이 source observable이자 트리거 역할을 한다.
Rx: combineLatest vs withLatestFrom
Observable이 방출하는 항목들마다 함수를 적용하고 최종 값을 마지막으로 방출한다. 기존에 Swift에 있는 reduce
와 유사하다.
let disposeBag = DisposeBag()
let source = Observable.of(1, 2, 3)
// 방법 1
source.reduce(0, accumulator: +)
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
// 방법 2
source.reduce(0, accumulator: {
summary, newValue in
return summary + newValue
}).subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
/* 실행 결과
6
*/
reduce와 유사한데 함수가 적용된 결과값을 계산 과정 중에 계속 방출해준다는 차이점이 있다.
이름 그대로 계산 과정을 스캔하는 느낌 👀
let disposeBag = DisposeBag()
let source = Observable.of(1, 2, 3, 5, 6)
source.scan(0, accumulator: +)
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
/* 실행 결과
1
3
6
11
17
*/