매거진 ReactiveX

You can make anything
by writing

C.S.Lewis

by Tilltue Aug 06. 2016

RxSwift, Filtering 알파벳 토토

Debounce, Distinct, Filter, Take, Skip등


* 이 포스트는 RxSwift 4.3.1, swift 4.2 버전을 기준으로 작성되었습니다.

이벤트들을 특정 조건이 맞을때 발생하도록이벤트를 필터링 하는 메서드들에 대해 알아보자



1. Debounce

http://rxmarbles.com/#debounce

지정한 시간간격 내에 마지막 하나의이벤트만 전달한다.

알파벳 토토

아래 그림처럼 이벤트 간격이 설정(debounce)한 시간대 값보다 짧은 타이밍으로 연속된다면 이벤트가 일어나지 않는다.

알파벳 토토




예제

let timer = Observable<Int.interval(3, scheduler: MainScheduler.instance)

timer.debounce(1, scheduler: MainScheduler.instance).debug()

.subscribe().disposed(by: disposeBag)


결과

2018-10-06 22:24:05.526:(timer) - Event next(0)

2018-10-06 22:24:06.527:(debounceTest()) - Event next(0)

2018-10-06 22:24:08.526:(timer) - Event next(1)

2018-10-06 22:24:09.528:(debounceTest()) - Event next(1)

2018-10-06 22:24:11.525:(timer) - Event next(2)

2018-10-06 22:24:12.526:(debounceTest()) - Event next(2)


시간값을 보면 3초마다 발생한 timer 가 발생하고 debounce 에서 설정한 1초 내에 다른 이벤트가 발생하지 않으므로1초뒤 debounce된 알파벳 토토에이벤트가 발생한다.


만약 debounce 에 4초를 설정한다면 이벤트는 3초내에 다시 발생하므로 무시되어

debounce된 알파벳 토토에 이벤트가발생되지 않는다.


- throttle

지정된 시간 내에 발생한 최초및 가장 최신의 이벤트를 발생시킨다.

debounce 와는 동작이 다르다.


예제

let timer = Observable<Int.interval(1, scheduler: MainScheduler.instance)

timer.throttle(3, scheduler: MainScheduler.instance).debug()

.subscribe().disposed(by: disposeBag)


결과

2018-10-06 22:29:34.234: (timer) - Event next(0)

2018-10-06 22:29:34.235:(throttleTest()) - Event next(0)

2018-10-06 22:29:35.234:(timer) - Event next(1)

2018-10-06 22:29:36.234:(timer) - Event next(2)

2018-10-06 22:29:37.234:(timer) - Event next(3)

2018-10-06 22:29:37.234:(throttleTest()) - Event next(3)

2018-10-06 22:29:38.234:(timer) - Event next(4)

2018-10-06 22:29:39.234:(timer) - Event next(5)


subscribe 된 시점에 이벤트가 발생되고, 이후 3초 간 발생한 이벤트중 가장 최근의 것을 발생시킨다.

유저 탭 이벤트등의 연속된 호출을 간단하게 필터링 할수 있다.


2. Distinct

http://rxmarbles.com/#distinct

이전 이벤트와 비교해서 값이 다를 경우에만 이벤트를 방출한다.

알파벳 토토

- distinctUntilChanged()

같은 원소인지 비교해서 다른 원소일때에만 이벤트가 방출된다.


예제

let test = [알파벳 토토;a알파벳 토토;,알파벳 토토;a알파벳 토토;,알파벳 토토;b알파벳 토토;,알파벳 토토;c알파벳 토토;,알파벳 토토;c알파벳 토토;,알파벳 토토;c알파벳 토토;]

let distinctTest = 알파벳 토토.from(test).distinctUntilChanged()

distinctTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(a)

next(b)

next(c)

completed


예제

struct Fish {

var name = 알파벳 토토;알파벳 토토;

var skinColor = 알파벳 토토;알파벳 토토;

}

let nimo = Fish(name: 알파벳 토토;nimo알파벳 토토;, skinColor: 알파벳 토토;red알파벳 토토;)

let dori = Fish(name: 알파벳 토토;dori알파벳 토토;, skinColor: 알파벳 토토;blue알파벳 토토;)

let dori2 = Fish(name: 알파벳 토토;dori2알파벳 토토;, skinColor: 알파벳 토토;blue알파벳 토토;)

let test = [nimo,nimo,dori,dori,dori2,nimo]

let distinctTest = 알파벳 토토.from(test).distinctUntilChanged { $0.skinColor }

distinctTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)


Equatable type 이 아닌 객체를 key 를 지정해서 비교할 수 있는 코드이다.

피부색을 비교하도록 했으므로, dori,dori2 는 같은 이벤트로 판단할 것이다.


결과

next((Fish #1)(name: 알파벳 토토;nimo알파벳 토토;, skinColor: 알파벳 토토;red알파벳 토토;))

next((Fish #1)(name: 알파벳 토토;dori알파벳 토토;, skinColor: 알파벳 토토;blue알파벳 토토;))

next((Fish #1)(name: 알파벳 토토;nimo알파벳 토토;, skinColor: 알파벳 토토;red알파벳 토토;))

completed


예제

let test = [nimo,nimo,dori,dori,dori2,nimo]

let distinctTest = 알파벳 토토.from(test).distinctUntilChanged { (lhs, rhs) - Bool in

return lhs.name == rhs.name

}

distinctTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)


위의 예제에서skinColor 가 아닌, name 값으로 비교하도록 변경한 것이다.


결과

next((Fish #1)(name: 알파벳 토토;nimo알파벳 토토;, skinColor: 알파벳 토토;red알파벳 토토;))

next((Fish #1)(name: 알파벳 토토;dori알파벳 토토;, skinColor: 알파벳 토토;blue알파벳 토토;))

next((Fish #1)(name: 알파벳 토토;dori2알파벳 토토;, skinColor: 알파벳 토토;blue알파벳 토토;))

next((Fish #1)(name: 알파벳 토토;nimo알파벳 토토;, skinColor: 알파벳 토토;red알파벳 토토;))

completed


3. ElementAt

http://rxmarbles.com/#elementAt

지정한 index 의 이벤트만 발생하도록 하는 메서드이다.


예제

let test = [알파벳 토토;a알파벳 토토;,알파벳 토토;a알파벳 토토;,알파벳 토토;b알파벳 토토;,알파벳 토토;c알파벳 토토;,알파벳 토토;c알파벳 토토;,알파벳 토토;c알파벳 토토;]

let elementAtTest = 알파벳 토토.from(test).elementAt(2)

elementAtTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(b)

completed


4. single ( First )

http://rxmarbles.com/#first

첫번째 이벤트만 발생시킨다.

RxSwift 에서는 single 메서드로 쓰인다.


예제 생략


5. Filter

http://rxmarbles.com/#filter

조건식에 부합하는 이벤트만 발생시킨다.


예제

let test = ["rabbit",알파벳 토토;fox알파벳 토토;,"fish","dog",알파벳 토토;cat알파벳 토토;]

let filterTest = 알파벳 토토.from(test).filter{ $0.hasPrefix(알파벳 토토;f알파벳 토토;) }

filterTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)


결과

next(fox)

next(fish)

completed


6. sample

http://rxmarbles.com/#sample

sampler 알파벳 토토 의이벤트에따라본래 알파벳 토토 의 이벤트가 전달된다.

전달할 이벤트가 없을때는 무시된다.


예제

let 알파벳 토토 = Observable<Int.interval(0.1, scheduler: MainScheduler.instance)

알파벳 토토.sample(알파벳 토토<Int.interval(0.5, scheduler: MainScheduler.instance))

.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(4)

next(9)

next(14)

next(19)

next(24)

...


0.1 초 이벤트가 발생하지만, 0.5초이벤트 Observable sampler를 통해, 위와 같은 결과를 보인다.


7. skip

http://rxmarbles.com/#skip

n개의 이벤트를 스킵한다.

예제

let test = ["rabbit",알파벳 토토;fox알파벳 토토;,"fish","dog",알파벳 토토;cat알파벳 토토;]

let skipTest = 알파벳 토토.from(test).skip(3)

skipTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(dog)

next(cat)

completed


- skipWhile

특정 이벤트 발생전까지 이벤트를skip 한다.


예제

let test = ["rabbit",알파벳 토토;fox알파벳 토토;,"fish","dog",알파벳 토토;cat알파벳 토토;]

let skipTest = 알파벳 토토.from(test).skipWhile{ $0 != 알파벳 토토;fish알파벳 토토; }

skipTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)


결과

next(fish)

next(dog)

next(cat)

completed


skipWhileWithIndex

deprecate 되었다. enumerate().skipWhile().map() 을 사용하면 된다.

skipWhile 과 기본적으로 동일하나 index 를사용할수 있다.


예제

let test = ["rabbit",알파벳 토토;fox알파벳 토토;,"fish",알파벳 토토;fox알파벳 토토;,알파벳 토토;cat알파벳 토토;]

let skipTest = 알파벳 토토.from(test).skipWhileWithIndex{ (item, index) - Bool in

return index < 3 || item != 알파벳 토토;fox알파벳 토토;

}

skipTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(fox)

next(cat)

completed


- skipUntil

http://rxmarbles.com/#skipUntil

다른 알파벳 토토의이벤트가 발생하기 전까지를 스킵한다.


예제

let 알파벳 토토 = Observable<Int.interval(0.1, scheduler: MainScheduler.instance)

알파벳 토토.skipUntil(알파벳 토토<Int.interval(0.5, scheduler: MainScheduler.instance))

.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(5)

next(6)

next(7)

next(8)

...


8. take

http://rxmarbles.com/#take

n개의 이벤트만 발생한다.


예제

let test = ["rabbit",알파벳 토토;fox알파벳 토토;,"fish","dog",알파벳 토토;cat알파벳 토토;]

let takeTest = 알파벳 토토.from(test).take(2)

takeTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(rabbit)

next(fox)

completed


- take withduration

일정 시간동안의 이벤트만 발생한다.


예제

let 알파벳 토토 = Observable<Int.interval(0.1, scheduler: MainScheduler.instance)

알파벳 토토.take(0.3, scheduler: MainScheduler.instance)

.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(0)

next(1)


- takeLast

http://rxmarbles.com/#takeLast

완료가 되면count 만큼 이전의 이벤트를 발생한다.

예제

let test = ["rabbit",알파벳 토토;fox알파벳 토토;,"fish","dog",알파벳 토토;cat알파벳 토토;]

let takeTest = 알파벳 토토.from(test).takeLast(2)

takeTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(dog)

next(cat)

completed


- takeUntil

http://rxmarbles.com/#takeUntil

다른 알파벳 토토 이벤트가 발생할때까지만 본래 알파벳 토토 의 이벤트를 발생한다.

예제

let 알파벳 토토 = Observable<Int.interval(0.1, scheduler: MainScheduler.instance)

알파벳 토토.takeUntil(알파벳 토토<Int.interval(0.5, scheduler: MainScheduler.instance))

.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(0)

next(1)

next(2)

next(3)

completed


- takeWhile

조건식에 부합될때까지만 이벤트를 발생한다.

예제

let test = ["rabbit",알파벳 토토;fox알파벳 토토;,"fish","dog",알파벳 토토;cat알파벳 토토;]

let takeWhileTest = 알파벳 토토.from(test).takeWhile{ $0 != 알파벳 토토;fish알파벳 토토; }

takeWhileTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)

결과

next(rabbit)

next(fox)

completed


takeWhileWithIndex

deprecate 되었다. enumerate().takeWhile().map() 을 사용하면 된다.

기본적으로 takeWhile 이며인덱스를사용할수 있다.


예제

let test = ["rabbit",알파벳 토토;fox알파벳 토토;,"fish",알파벳 토토;fox알파벳 토토;,알파벳 토토;cat알파벳 토토;]

let takeWhileTest = 알파벳 토토.from(test).takeWhileWithIndex{ (item,index) - Bool in

return index < 2

}

takeWhileTest.subscribe{ event in

print(event)

}.disposed(by: disposeBag)


결과

next(rabbit)

next(fox)

completed


9. IgnoreElements

모든 이벤트를 무시한다.

발생되는 이벤트에는 관심이 없고, 에러나 완료만이 의미가 있을때 사용된다.




이벤트를 필터링 할 수 있는 메서드들을 알아보았다.

브런치는 최신 브라우저에 최적화 되어있습니다. IE chrome safari