안녕하세요🐶
빈지식 채우기의 비니🙋🏻♂️ 입니다.
이전 포스팅에서는 RxSwift에 Operator에 대해 알아보았습니다.
이번 포스팅에서는 RxSwift에서 자주 사용되는 Operator에 대해 알아보도록 하겠습니다.
자~! 그럼 고고씽~!
1. Create
가장 먼저 Observable을 생성하는 Operator에 대해 알아보도록 하겠습니다.
1-1. create
가장 기본적으로 Observable을 생성하는 것으로, Observable을 직접 구현하고 싶을 때 사용합니다.
Observable<Int>.create { (ob) -> Disposable in
ob.onNext(94) // (1)
ob.onCompleted()
return Disposables.create()
}
.subscribe {
print($0) // (2)
}
.disposed(by: disposeBag)
1. onNext를 통해 구독자에게 94를 방출합니다.
2. subscribe 구독을 함으로써 94를 받아 처리한다. 결과는 아래와 같습니다.
1-2. just
just란 하나의 항목을 방출하는 Observable을 생성합니다. 파라미터의 하나의 요소를 받아 생성합니다.
// just로 Observable 생성
Observable.just(94) // (1)
.subscribe { date in
print(date) // (2)
}
.disposed(by: disposeBag)
1. just를 통해 94의 값을 받아 처리합니다.
2. subscribe 구독을 함으로써 94를 받아 처리한다. 결과는 아래와 같습니다.
1-3. from
from의 경우 파라미터로 배열을 받는데, 배열에 저장된 요소를 하나씩 순서대로 방출하는 Observable을 생성합니다.
// from로 Observable 생성
Observable.from([94, 2, 19]) // (1)
.subscribe {
print($0) // (2)
}
.disposed(by: disposeBag)
1. from를 통해 배열의 값을 받아 처리합니다.
2. subscribe 구독을 함으로써 배열의 값을 하나씩 받아 처리한다. 결과는 아래와 같습니다.
1-4. of
2개 이상의 요소를 방출하는 Observable을 만들고 싶을 때 사용합니다.
// of로 Observable 생성
Observable.of("94", "2", "19") // (1)
.subscribe {
print($0) // (2)
}
.disposed(by: disposeBag)
1. of를 통해 2개 이상의 값을 받아 처리합니다.
2. subscribe 구독을 함으로써 2개 이상의 값을 하나씩 받아 처리한다. 결과는 아래와 같습니다.
2. Transform
생성된 Observable을 통해 방출된 결과를 변환하는 Operator입니다.
2-1. map
방출된 결과를 원하는 값으로 변형해서 방출시킬 수 있습니다.
RX 공식 문서에는 다음과 같이 설명이 되어 있습니다.
말 그대로 각각의 요소를 map을 통해 새로운 요소로 변환해준다는 것이다. 예시를 통해 확인해보겠습니다.
// map으로 원하는 값으로 변형하여 방출
Observable.from([94, 2, 19]) // (1)
.map{
$0 * 10 // (2)
}
.subscribe {
print($0)
}
.disposed(by: disposeBag)
1. from 을 통해 배열의 값을 파라미터로 받습니다.
2. map Operator를 통해 결과를 변형하여 방출합니다. 결과는 아래와 같습니다.
2-2. flatMap
map과 비슷하게 결과를 변형시켜 방출하지만, Observable을 자체를 바꿔서 Observable을 방출합니다.
Observable에 의해 방출된 항목을 Observable로 변환한 뒤 단일 Observable로 평면화 하는 기능이다.
흠..이해가 잘 안가는데 예시로 확인을 해보시죠!
// flatMap을 통해 새로운 Observable 방출
let ob1 = Observable.of("a", "b", "c")
let ob2 = Observable.of("1", "2", "3")
ob1.flatMap{ (x: String) -> Observable<String> in // (1)
return ob2.map{ // (2)
x + $0
}
}
.subscribe{
print($0)
}
.disposed(by: disposeBag)
1. ob1의 Observable 의 요소들을 flatMap을 합니다.
2. ob2.map을 통해 ob2의 각 요소에 ob1의 요소들을 합쳐 새로운 Observable이 생성됩니다.
2번 과정이 3번 반복되어 생성된 3개의 Observable을 flatMap을 통해 평면화를 진행한다.
?? 3개의 Observable 이라고?? 무슨 말인지 모르겠는데..? 보기 쉬운 다이어그램으로 확인해보자..😥
1. flatMap을 통해 3개의 Observable (1) (2) (3) 이 생성됩니다.
2. 각각의 Observable에서 방출하는 아이템들이 하나의 Observable로 되어 ( 평탄화 작업 ) (4)와 같은 결과를 얻을 수 있습니다.
3. Filter
생성된 Observable을 결과를 필터링하는 Operator입니다.
3-1. filter
결과를 원하는 값에 맞게 필터링하여 걸러낼 수 있습니다.
// 방출하는 결과를 원하는 값에 맞게 필터링
Observable.from([94, 2, 19]).filter {
$0 % 2 == 0 // (1)
}
.subscribe {
print($0)
}
.disposed(by: disposeBag)
1. 2로 나누었을 때 나머지 값이 0인 요소만 필터링을 합니다.
3-2. takeLast
결과를 끝에서부터 몇번째까지 방출할지 결정할 수 있습니다.
// 방출하는 결과 중 끝에서 몇번째까지 방출할지 결정
Observable.from([94, 2, 19]).takeLast(2) // (1)
.subscribe {
print($0)
}
.disposed(by: disposeBag)
1. 끝에서 2번째 값까지 방출되게 결정합니다.
3-3. elementAt
결과 중 원하는 인덱스의 결과를 방출할 수 있습니다.
// 방출하는 결과 중 원하는 인덱스 값에 대한 요소를 방출
Observable.from([94, 2, 19]).element(at: 2) // (1)
.subscribe {
print($0)
}
.disposed(by: disposeBag)
1. 두 번째 인덱스의 값을 방출되게 결정합니다.
4. Combine
생성된 Observable을 결과를 합치는 Operator입니다.
4-1. combineLatest
두 Observable의 각각의 이벤트가 발생할 때, 두 Observable의 마지막 이벤트들을 묶어서 방출한다.
// 두 Observable의 가장 최근의 값끼리 합쳐서 하나의 값으로 만든 후 방출합니다.
let ob1 = PublishSubject<String>()
let ob2 = PublishSubject<String>()
let observable = Observable.combineLatest(ob1, ob2) { (first:String, second:String) in
return (first, second)
}
let disposable = observable.subscribe(
onNext: {
(String) in print(String)
}
)
ob1.onNext("a")
ob2.onNext("1")
ob1.onNext("b")
ob2.onNext("2")
ob2.onNext("3")
ob2.onNext("4")
ob1.onNext("c")
ob1.onNext("d")
ob1.onNext("e")
disposable.dispose()
이해가 안되니 바로 다이어그램으로 확인해보겠습니다.
1. ob1 에서 a라는 값이 먼저 방출된다.
2. 그 이후 ob2에서 1이라는 값이 방출됨으로써 combineLatest 로 a1 이라는 값이 최종적으로 방출된다.
3. 이후 ob1에서 b라는 값이 방출되고 현재 b 입장에서 ob2의 가장 최근 값은 1이므로 b1이 방출된다.
4. 그 이후 ob2에서 2, 3, 4 3개의 값이 방출되고 차례대로 b2, b3, b4가 방출된다.
5. 마지막으로 ob1에서 차례대로 c, d, e가 방출되었고 ob2에서의 최근 값은 4이므로 c4, d4, e4가 방출된다.
예시의 결과 값은 아래와 같습니다.
4-2. zip
combineLatest와 매우 유사하지만, 두개의 Observable에서 새로운 이벤트가 발생되어야만 방출 ( 1:1 매칭 ) 한다는 차이점이 있다.
// 두 Observable의 새로운 이벤트가 발생했을때만 방출합니다. (1:1 매칭)
let ob3 = PublishSubject<String>()
let ob4 = PublishSubject<String>()
let observable2 = Observable.zip(ob3, ob4) { (first:String, second:String) in
return (first, second)
}
let disposable2 = observable2.subscribe(
onNext: {
(String) in print(String)
}
)
ob3.onNext("a")
ob4.onNext("1")
ob3.onNext("b")
ob4.onNext("2")
ob4.onNext("3")
ob4.onNext("4")
ob3.onNext("c")
disposable2.dispose()
무슨소리냐고? 다이어그램으로 확인해보자.
1. ob3에서 a라는 값이 먼저 방출됩니다.
2. 그 이후 ob4에서 1이라는 값이 방출되었고 zip을 통해 a1이 방출됩니다.
3. 이후 ob3에서 b를 방출하였으나 ob4에서 새로운 이벤트가 방출이 되지 않았으므로 따로 방출하지 않습니다.
4. ob4에서 3이 방출되었고 zip을 통해 b3가 방출됩니다.
이상으로 Operator 포스팅을 마치겠습니다.
전체 소스는 아래에 같이 첨부하도록 하겠습니다.
import Foundation
import RxSwift
import RxCocoa
class Operator {
let disposeBag = DisposeBag()
// Observable 생성
func create() {
print("----------------------------------------------------------")
Observable<Int>.create { (ob) -> Disposable in
ob.onNext(94)
ob.onCompleted()
return Disposables.create()
}
.subscribe {
print($0)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
// just로 Observable 생성
Observable.just(94)
.subscribe { date in
print(date)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
// from로 Observable 생성
Observable.from([94, 2, 19])
.subscribe {
print($0)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
// of로 Observable 생성
Observable.of("94", "2", "19")
.subscribe {
print($0)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
}
// 방출하는 결과를 변환하는 Observable
func transform() {
print("----------------------------------------------------------")
// map으로 원하는 값으로 변형하여 방출
Observable.from([94, 2, 19])
.map{
$0 * 10
}
.subscribe {
print($0)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
// flatMap을 통해 새로운 Observable 방출
let ob1 = Observable.of("a", "b", "c")
let ob2 = Observable.of("1", "2", "3")
ob1.flatMap{ (x: String) -> Observable<String> in
return ob2.map{
x + $0
}
}
.subscribe{
print($0)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
}
// 방출하는 결과를 필터링하는 Observable
func filter() {
print("----------------------------------------------------------")
// 방출하는 결과를 원하는 값에 맞게 필터링
Observable.from([94, 2, 19]).filter {
$0 % 2 == 0
}
.subscribe {
print($0)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
// 방출하는 결과 중 끝에서 몇번째까지 방출할지 결정
Observable.from([94, 2, 19]).takeLast(2)
.subscribe {
print($0)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
// 방출하는 결과 중 원하는 인덱스 값에 대한 요소를 방출
Observable.from([94, 2, 19]).element(at: 2)
.subscribe {
print($0)
}
.disposed(by: disposeBag)
print("----------------------------------------------------------")
}
// 방출하는 결과를 합치는 Observable
func combine() {
print("----------------------------------------------------------")
// 두 Observable의 가장 최근의 값끼리 합쳐서 하나의 값으로 만든 후 방출합니다.
let ob1 = PublishSubject<String>()
let ob2 = PublishSubject<String>()
let observable = Observable.combineLatest(ob1, ob2) { (first:String, second:String) in
return (first, second)
}
let disposable = observable.subscribe(
onNext: {
(String) in print(String)
}
)
ob1.onNext("a")
ob2.onNext("1")
ob1.onNext("b")
ob2.onNext("2")
ob2.onNext("3")
ob2.onNext("4")
ob1.onNext("c")
ob1.onNext("d")
ob1.onNext("e")
disposable.dispose()
print("----------------------------------------------------------")
// 두 Observable의 새로운 이벤트가 발생했을때만 방출합니다. (1:1 매칭)
let ob3 = PublishSubject<String>()
let ob4 = PublishSubject<String>()
let observable2 = Observable.zip(ob3, ob4) { (first:String, second:String) in
return (first, second)
}
let disposable2 = observable2.subscribe(
onNext: {
(String) in print(String)
}
)
ob3.onNext("a")
ob4.onNext("1")
ob3.onNext("b")
ob4.onNext("2")
ob4.onNext("3")
ob4.onNext("4")
ob3.onNext("c")
disposable2.dispose()
print("----------------------------------------------------------")
}
}
다음 포스팅은 Subject에 대해 알아보겠습니다.
감사합니다~~
참고
'iOS 🖥️ > RxSwift' 카테고리의 다른 글
[RxSwift] Traits ( Single, Maybe, Completable ) (0) | 2024.01.18 |
---|---|
[RxSwift] Debounce, Throttle (0) | 2024.01.17 |
[RxCocoa] Driver (0) | 2024.01.17 |
[RxCocoa] Relay (2) | 2024.01.16 |
[ RXSwift ] Subject (2) | 2024.01.15 |