[RxSwift] Operator란?

2021. 6. 21. 02:18RxSwift

반응형

오늘은 간단하게 RxSwift에서 유용하게 사용되는 Operator들에 대해서 어떻게 동작하는지 알아보겠습니다~ 

 

RxSwift Operator

Operator를 이용하면 Observable로 들어오는 이벤트들을 여러가지 방식으로 연산이 가능하게 됩니다.

여러가지 OperatorReactiveX에 있는 범주에 따라 자주 사용하는 Operator를 알아보겠습니다..!!

크게 3가지로 나누어서 알아보겠습니다.

  • Transforming Observables
  • Filtering Observables
  • Combining Observables

 

Transforming Operators

 

1. map

  • 방출된 이벤트를 특정 함수를 적용하여 새로운 이벤트로 변형하여 방출시킵니다. (Swift의 map 함수와 동일합니다.)

Observable.just(10)
    .map { $0 * 2 }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: self.disposeBag)

/* 
20
*/

 

2. flatMap

  • 방출된 이벤트로부터 새로운 Observable로 변형하여 방출합니다.
  • 보통 API를 통해 새로운 Observable로 변형해서 호출할 때, 사용할 수 있습니다.

func requestAPI(url: String) -> Observable<Data> {
    return Observable.create { ob in
        guard let url = URL(string: url) else {
            ob.onError(NSError(domain: "url error", code: -1, userInfo: nil))
            return Disposables.create()
        }
            
        URLSession.shared.dataTask(with: url) { data, res, err in
            guard let data = data else {
                ob.onError(NSError(domain: "request error", code: -2, userInfo: nil))
                return
            }
            ob.onNext(data)
            ob.onCompleted()
        }.resume()
            
        return Disposables.create()
    }
}

Observable.just("https://api.github.com")
        .flatMap { url -> Observable<Data> in
            return APIService.requestAPI(url: url)
        }
        .subscribe(onNext: { data in
            let decoding = try? JSONDecoder().decode(Int.self, from: data)
            print(decoding)
        })
        .disposed(by: disposeBag)

// 일단은 API를 아무거나 입력을 했는데, 최종적으로 API로부터 불러온 데이터를 디코딩해서 출력해줍니다.

 

3. flatMapLatest

  • 기본적으로 flatMap과 동일하게 작동합니다.
  • 다른 점은 가장 최신의 값만을 다루고 싶을 때, 사용하는 Operator입니다.

struct Student {
    var score: BehaviorRelay<Int>
}

let john = Student(score: BehaviorRelay(value: 75))
let mary = Student(score: BehaviorRelay(value: 95))

let student = PublishSubject<Student>()
        
student.flatMapLatest { $0.score }
    .subscribe(onNext: {
        print($0)
    }).disposed(by: disposeBag)
        
student.onNext(john)
john.score.accept(100)
        
student.onNext(mary)
mary.score.accept(80)
        
john.score.accept(43)
mary.score.accept(90)

/*
75 john
100 john
95 mary
80 mary
90 mary
*/

/* FlatMap을 사용한다면
75 john
100 john
95 mary
80 mary
43 john
90 mary
*/

// flatMapLatest의 이 전에 john로 들어온 Observable 타입은 구독하지 않는다.

 

 

Filtering Operators

 

1. filter

  • 방출된 이벤트 중 조건에 맞는 이벤트만을 방출시킵니다. (Swift의 filter와 동일하게 동작합니다.)

Observable.from([1, 2, 3, 4, 5, 6, 7, 8])
    .filter { $0 % 2 == 0 }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/*
2 
4
6
8
*/

 

2. take

  • 처음으로 들어오는 n개의 이벤트만 방출합니다.

Observable.from([1, 2, 3, 4, 5, 6, 7, 8])
    .take(2)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/*
1
2
*/

 

3. skip

  • 처음 방출되는 n개의 이벤트는 방출하지 않고 이후부터 방출합니다.

Observable.from([1, 2, 3, 4, 5, 6, 7, 8])
    .skip(2)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/*
3
4
5
6
7
8
*/

 

4. distinctUntilChanged

  • 연속으로 같은 값이 방출되지 않도록 합니다.

Observable.from([1, 2, 3, 3, 4])
    .distinctUntilChanged()
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/*
1
2
3
4
*/

 

5. throttle

  • 지정한 시간동안 처음 들어오는 이벤트를 방출합니다.
  • latest라는 변수에 값에 따라 이벤트를 다르게 방출합니다. false일 경우, 처음에 들어온 이벤트만 방출합니다. true일 경우, 처음과 마지막의 이벤트를 방출합니다. (밑은 false일 경우입니다.)

self.cancelButton.rx.tap
    .throttle(.seconds(1), latest: false, scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print("Tap")
    })
    .disposed(by: self.disposeBag)
    
/* 1초에 3번 탭할 경우 (처음의 이벤트만 방출)
Tap
*/


self.cancelButton.rx.tap
    .throttle(.seconds(1), latest: true, scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print("Tap")
    })
    .disposed(by: self.disposeBag)
    
/* 1초에 3번 탭할 경우 (처음과 마지막 이벤트 방출)
Tap
Tap
*/

 

6. debounce

  • 지정한 시간동안 들어온 이벤트 중, 가장 최신의 이벤트를 방출합니다.

 self.cancelButton.rx.tap
     .debounce(.seconds(1), scheduler: MainScheduler.instance)
     .subscribe(onNext: {
         print("Tap")
     })
     .disposed(by: self.disposeBag)
     
/* 1초에 3번 탭한 경우 (가장 마지막만 방출)
Tap
*/

 

 

Combining Operators

 

1. combineLatest

  • 두개 이상의 Observable 중, 가장 최근의 이벤트가 방출될 때 이벤트를 전부 방출합니다.
  • 둘 중, 어느 하나라도 방출하지 않은 Observable이 있다면 방출하지 않습니다.

let first = Observable.from([1, 2, 3])
let secont = Observable.from(["A", "B", "C"])

Observable.combineLatest(first, second)
    .subscribe(onNext: {
        print("\($0) + \($1)")
    })
	  .disposed(by: disposeBag)

/*
1 + A
2 + A
2 + B
3 + B
3 + C
*/

 

2. zip

  • 두 개 이상의 Observable 중, 이벤트를 방출하면 순서가 맞는 쌍끼리 하나의 이벤트를 방출합니다.
  • combineLatest는 최신의 이벤트를 이전의 이벤트와 합치지만 zip은 순서가 맞는 쌍끼리 엮습니다.

let first = Observable.from([1, 2, 3])
let secont = Observable.from(["A", "B", "C"])

Observable.zip(first, second)
    .subscribe(onNext: {
        print("\($0) + \($1)")
    })
	  .disposed(by: disposeBag)

/*
1 + A
2 + B
3 + C
*/

 

3. merge

  • 여러 개의 Observable을 합치지만 위의 두 Operator와 다르게 하나의 이벤트를 받을 수 있다.
  • 공통의 로직을 실행해야할 경우 사용하면 유용하다.

let first = Observable.from([1, 2, 3])
let secont = Observable.from([4, 5, 6])

Observable.merge(first, second)
    .subscribe(onNext: {
        print("\($0)")
    })
	  .disposed(by: disposeBag)

/*
1
4
2
5
3
6
*/

 

이렇게 대표적으로 RxSwift에서 사용하는 Operator들을 알아보았습니다.

도움이 되었으면 좋겠네요 :)

반응형

'RxSwift' 카테고리의 다른 글

[RxSwift] Hot & Cold Observable  (0) 2021.05.05
[RxSwift] RxSwift란 - Observable, Disposable  (0) 2021.02.11