Filtering Operators
1.Ignore
위와 같은 시퀀스가 하나 있다고 하자. 해당 시퀀스가 세 가지 값을 가지고 있다고 할 때, ignoreElements()
를 호출하면
아래와 같은 사진처럼 모든 element가 무시된다. 그러고 나서는 onCompleted() 메서드가 호출된다.
여기까지만 봐서는 무슨 말인지 이해가 잘 가지 않을 것이다. 예제를 통해 한번 살펴보자.
예제
예를 들어 다음과 같은 코드가 있다고 할 때, strikes는 subscribe하기 이전에 ignoreElements() 를 호출했기 때문에 strikes가 아무리 onNext()를 호출해도 클로저 내부의 함수가 실행되지 않는다.
// filtering operators
let strikes = PublishSubject<String>()
let disposeBag = DisposeBag()
strikes
.ignoreElements()
.subscribe { _ in
print("[Subscription is called]")
}.disposed(by: disposeBag)
strikes.onNext("A")
strikes.onNext("B")
strikes.onNext("C")
// 아무것도 출력되지 않음.
다만 onCompleted() 까지 Ignore하는 것은 아니라서,
onCompleted 시점에서는 함수가 호출된다.
그래서 위 예시 코드에서 strikes.onCompleted()
한 줄만 추가하면 [Subscription is called]
이 출력된다.
// filtering operators
let strikes = PublishSubject<String>()
let disposeBag = DisposeBag()
strikes
.ignoreElements()
.subscribe { _ in
print("[Subscription is called]")
}.disposed(by: disposeBag)
strikes.onNext("A")
strikes.onNext("B")
strikes.onNext("C")
// 다음의 한 줄을 추가.
strikes.onCompleted()
// [Subscription is called] 출력.
elementAt
만약 위와 같은 시퀀스가 있고,
여기서 elementAt(1)을 호출한다면,
이것은 다음과 같이 [1] 번째 인덱스에 있는 '2'를 반환한다. (인덱스는 0부터 시작.)
코드로 설명하자면
예를 들어 다음과 같은 코드가 있다고 하자.
// filtering operators - elementAt
let strikes = PublishSubject<String>()
let disposeBag = DisposeBag()
strikes.elementAt(2)
.subscribe(onNext: { _ in
print("Index Reached")
}).disposed(by: disposeBag)
여기서 우리는 subscribe를 했으므로, onNext시에 우리가 의도한 index reached
라는 문구가 떠야 한다.
그러나 위의 예제에 아래 코드를 추가해보면, elementAt의 인자로 들어온 2, 그러니까 세 번째 인자가 들어오기 전까지는 아무것도 출력되지 않는 것을 알 수 있다.
strikes.onNext("X")
strikes.onNext("Y")
//여기서 실행했을 때에는 아무것도 안 뜸.
strikes.onNext("Z")
// print됨: Index Reached
Filter
Filter
는 예를 들어 위와 같은 시퀀스가 있고, $0 < 3
이라는 filter 옵션을 주면 특정 개수만큼(위에서는 2개) 시퀀스를 필터링하여 전달해주는 역할을 한다. 구체적으로 무슨 말인지 아래에서 더 살펴보자.
Observable.of(1, 2, 3, 4, 5, 6, 7) 을 subscribe하면 1부터 7까지 onNext 이벤트가 발생하게 된다.
그러면 여기에 { $0 % 2 == 0 }
이라는 옵션을 주고 subscribe를 한다면 어떤 일이 발생할까?
코드로 살펴보자.
// filtering operators - elementAt
let disposeBag = DisposeBag()
Observable.of(1, 2, 3, 4, 5, 6, 7)
.filter { $0 % 2 == 0 }
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
예를 들어 위와 같은 코드가 있다고 할 때, 1부터 7까지의 요소를 담은 Observable을 $0 % 2 == 0
으로 필터링하고,
onNext를 subscribe한 결과는 무엇일까?
답은 다음과 같다. 쉽게 예상할 수 있었을 것이다.
2
4
6
Skip
위와 같이 세 개의 시퀀스가 있다고 할 때, 앞의 두 개 시퀀스를 뛰어넘고 싶다고 하면 skip(2)
를 호출하면 된다.
그렇게 하면 3이라는 시퀀스만 가져올 수 있다.
코드로 살펴보자.
let disposeBag = DisposeBag()
Observable.of("A", "B", "C", "D", "E", "F")
.skip(3)
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
위와 같이 A~F 의 요소를 갖는 Observable을 subscribe하는데, skip(3)
이라는 옵션을 붙여줬다.
결과가 어떨 것 같은가?
결과는 A, B, C를 제외하고 네 번째 요소인 D부터 차례로 onNext event를 호출한다.
출력값은 다음과 같다.
D
E
F
skipWhile
이번에도 위와 같은 세 개의 시퀀스가 있다고 해보자.
만약 해당 시퀀스에서 skipWhile { $0 % 2 == 1 }
, 그러니까 홀수를 스킵한다
정도로 해석할 수 있는 조건을 준다면,
다음과 같이 2, 3을 반환한다.
이러한 결과가 나오는 것은 skipWhile이 이름 그대로 조건을 만족하는 동안 skip
하기 때문이다.
이해를 돕기 위해 코드로 살펴보자.
let disposeBag = DisposeBag()
Observable.of(1, 1, 2, 2, 3, 3, 4, 4, 5, 5)
.skipWhile { $0 % 2 == 1 }
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
예를 들어 위와 같은 경우 어디까지 스킵할 것 같은가?
1, 3, 5가 필터링 될까? 아니면 제일 앞의 두 개의 요소 1, 1만 필터링될까?
정답은 다음 코드를 확인하시길..
2
2
3
3
4
4
5
5
skipUntil
skipUntil에 대해 알아보자.
skipUntil이란, 어떤 특정 trigger를 세워놓고 해당 trigger에서 이벤트가 일어나기 전까지 모두 skip해버리는 것을 의미한다.
아래 사진을 한번 보자.
위 사진에서 1과 2 사이에 trigger가 당겨졌다면, 1은 스킵되고 2와 3이라는 시퀀스만 실행된다.
무슨 말을 하고 싶은 건지 감을 잡았겠지만 정확히 어떤 상황인지 이해가 가지 않을 것이다.
코드로도 한번 살펴보자.
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
subject.skipUntil(trigger)
.subscribe(onNext: {
print ($0)
}).disposed(by: disposeBag)
subject.onNext("A")
subject.onNext("B")
subject.onNext("C")
예를 들어 위와 같이 trigger
에서는 이벤트가 일어나지 않고 subject에서만 이벤트가 일어나는 상황에서,
subject에 skipUntil(trigger)
라는 조건을 주게 된다면 위 상황에서는 아무것도 출력되지 않는다.
왜냐하면 우리가 준 조건은 trigger에 이벤트가 일어나기 전까지는 모두 skip하라는 조건이기 때문이다.
그래서 위 코드를 아래와 같이 바꿔보면 무언가 출력이 될 것이다.
무엇이 출력될지 예상하면서 코드를 읽어보자.
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
subject.skipUntil(trigger)
.subscribe(onNext: {
print ($0)
}).disposed(by: disposeBag)
subject.onNext("A")
subject.onNext("B")
subject.onNext("C")
trigger.onNext("Something")
subject.onNext("D")
subject.onNext("E")
subject.onNext("F")
결과는 다음과 같이 출력됐다:
D
E
F
take
위와 같은 시퀀스에 대해 take(2)를 호출하면, (첫) 두 개의 시퀀스를 가져오겠다는 것을 의미한다.
즉, (1, 2) 를 가져오겠다는 것인데, 이에 대해 코드로 살펴보자.
let disposeBag = DisposeBag()
Observable.of(1,2,3,4,5,6)
.take(3)
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
위와 같은 경우 1~6까지의 번호(시퀀스)에 대해 take(3)
를 호출하고 있다.
이에 대한 결과는 다들 예상하겠지만 다음과 같다.
1
2
3
takeWhile
예를 들어 위와 같은 시퀀스가 있다고 할 때,
takeWhile{ $0 % 2 == 0 }
이라는 조건은 시퀀스가 짝수인 동안만 동작한다.
위의 사진에서는 2와 4라는 시퀀스만 전달된다는 의미이다.
이것 또한 코드로 한번 살펴보자.
let disposeBag = DisposeBag()
Observable.of(2,4,6, 7, 8,10)
.takeWhile {
return $0 % 2 == 0
}.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
위 예제코드의 결과는 2, 4, 6으로, 7을 만나기 전까지만 출력된다.
그 이유는 조건이 짝수인 동안만 이벤트를 받는 것이기 때문이다.
(참고로 코드에 쓰인 return문은 쓰나 안 쓰나 결과는 같다.)
takeUntil
takeUntil
은 skipUntil과 마찬가지로 어떤 trigger를 요구한다.
예를 들어 아래 이미지에서 2와 3 사이에 어떤 trigger가 당겨졌다면,
1과 2만 전달되는 것이 takeUntil이다.
코드로 설명하자면 아래 예시에서 trigger되는 부분을 잘 살펴보자.
let disposeBag = DisposeBag()
let subject = PublishSubject<String>()
let trigger = PublishSubject<String>()
subject.takeUntil(trigger)
.subscribe(onNext: {
print($0)
}).disposed(by: disposeBag)
subject.onNext("A")
subject.onNext("B")
subject.onNext("C")
trigger.onNext("X")
subject.onNext("D")
subject.onNext("E")
subject.onNext("F")
위와 같이 trigger "X"를 호출하는 시점이 ABC "X" DEF인 경우 출력은 당연히 X 이전의 요소들, 즉
A
B
C
가 된다.
'iOS::스위프트(swift) > RxSwift+MVVM' 카테고리의 다른 글
RxSwift 기초 5 - Combining Operators (0) | 2021.06.08 |
---|---|
RxSwift 기초 4 - Operator Transforming (0) | 2021.06.07 |
RxSwift 기초2 - dispose와 subject (0) | 2021.05.21 |
RxSwift 기초 - observable과 subscribe (0) | 2021.05.17 |
swift MVVM 정리 및 예제 (8) | 2021.03.28 |
최근댓글