Search

RxSwift - Filtering Operator

 Filtering Operator

Filtering Operator는 Observable의 item를 선택적으로 방출해주는 Operator 입니다.
위의 문장을 좀 더 쉽게 이해하기 위해서 우리가 자주 사용하는 “이모지”창을 볼게요.
이모지 화면
이모지는 너무 많기 때문에 내가 원하는 이모지를 찾고 싶다면 상단에 있는 검색 부분을 눌러서 원하는 이모지 이름을 넣으면 됩니다. 저는 우는 이모지를 찾고 싶기 때문에 눈물 이라고 검색해보겠습니다.
우는 이모지 화면
제가 원하는 우는 이모지들만 잔뜩 나왔네요.
검색창처럼 내가 원하는 값만 걸러내서 가져다 주는 것이 Filtering Operator 입니다.
근데, Operator는 코드의 아무 부분이나 쓰면 적용이 되는건가요?
아닙니다. Operator는 .next 이벤트에 조건부 제약 조건을 적용하는 겁니다.
따라서, 이벤트를 보내줄 Observable과 이벤트를 어떻게 처리할 것인지가 나타나 있는 next 사이에 Operator를 두면 됩니다. 하단 코드처럼 말이죠.
Observable .filter { $0 < 10 } // 이 부분에 작성 .subscribe { print($0) } .disposed(by: bag)
Swift
복사

 Filtering Operator의 종류

Ignoring Operators

ignoreElements

next 이벤트를 무시하고 .error.completed를 전달
ignoreElements는 .error.completed를 전달하기 때문에 종료되는 시점만 알 수 있습니다.
let hamster = PublishSubject<String>() let bag = DisposeBag() hamster .ignoreElements() .subscribe (onNext: { food in print("햄스터가 먹은 \(food)") }, onCompleted: { print("햄스터 배부름") }) .disposed(by: bag) hamster.onNext("햄버거") hamster.onNext("소시지") hamster.onNext("햄") hamster.onCompleted() /* 햄스터 배부름 */
Swift
복사

element(at:)

발생한 이벤트 중에 입력한 index번호의 이벤트만 수신
let hamster = PublishSubject<String>() let bag = DisposeBag() hamster .element(at: 1) .subscribe (onNext: { food in print("햄스터가 먹은 \(food)") }, onCompleted: { print("햄스터 배부름") }) .disposed(by: bag) hamster.onNext("햄버거") hamster.onNext("소시지") hamster.onNext("햄") hamster.onCompleted() /* 햄스터가 먹은 소시지 햄스터 배부름 */
Swift
복사

filter

방출할 이벤트에 대한 조건을 걺
filter는 내부에 조건문을 명시적으로 걸어서 요소들을 필터링합니다.
let books = ["데미안", "1984", "인간실격", "동물농장", "모모"] let bag = DisposeBag() Observable.from(books) .filter { $0.count > 3 } .subscribe (onNext: { book in print("내가 본 \(book)") }, onCompleted: { print("지식 충전 완료") }) .disposed(by: bag) /* 내가 본 1984 내가 본 인간실격 내가 본 동물농장 지식 충전 완료 */
Swift
복사

Skipping Operators

skip

처음 발생하는 n(입력한 개수)개의 이벤트를 skip
let books = ["데미안", "1984", "인간실격", "동물농장", "모모"] let bag = DisposeBag() Observable.from(books) .skip(5) .subscribe (onNext: { book in print("내가 본 \(book)") }, onCompleted: { print("지식 충전 완료") }) .disposed(by: bag) /* 지식 충전 완료 */
Swift
복사

skip(while:)

특정 조건이 false일 때까지 skip하고 그 이후의 요소들은 방출
filter와 기능이 유사하지만 ⓵ 조건을 통과하는 경우에 값을 skip한다는 점이 다릅니다. ⓶ 한 번 특정 조건을 만족하고 나면 그 이후에는 조건에 상관없이 모든 값을 방출합니다.
let books = ["데미안", "1984", "인간실격", "동물농장", "모모"] let bag = DisposeBag() Observable.from(books) .skip { $0 != "인간실격" } .subscribe (onNext: { book in print("내가 본 \(book)") }, onCompleted: { print("지식 충전 완료") }) .disposed(by: bag) /* 내가 본 인간실격 내가 본 동물농장 내가 본 모모 지식 충전 완료 */
Swift
복사

skip(until:)

다른 Observable에서 이벤트가 발생하기 전까지 발생한 이벤트를 skip
let kDaughterHamster = PublishSubject<String>() let kFatherHamster = PublishSubject<String>() let bag = DisposeBag() kDaughterHamster .skip(until: kFatherHamster) .subscribe (onNext: { food in print("딸랑구 햄스터가 먹은 \(food)") }, onCompleted: { print("딸랑구 햄스터 배부름") }).disposed(by: bag) kDaughterHamster.onNext("햄버거") kDaughterHamster.onNext("소시지") kDaughterHamster.onNext("햄") kFatherHamster.onNext("삼겹살") kDaughterHamster.onNext("나물") // 유교걸 딸랑구 햄스터는 아빠 햄스터가 수저를 들기 전까지 음식을 먹지 못합니다. /* 딸랑구 햄스터가 먹은 나물 */
Swift
복사

Taking Operators

take

입력한 개수만큼의 이벤트를 받고 나머지는 무시
skip과는 반대로 처음 n(입력한 개수)개의 요소들만 방출합니다.
let books = ["데미안", "1984", "인간실격", "동물농장", "모모"] let bag = DisposeBag() Observable.from(books) .take(3) .subscribe (onNext: { book in print("내가 본 \(book)") }, onCompleted: { print("지식 충전 완료") }) .disposed(by: bag) /* 내가 본 데미안 내가 본 1984 내가 본 인간실격 지식 충전 완료 */
Swift
복사

take(while:)

특정조건이 false일 때까지 이벤트를 방출
skip(while:)과는 반대로 특정 조건이 false 일 때까지만 이벤트를 방출합니다.
let books = ["데미안", "1984", "인간실격", "동물농장", "모모"] let bag = DisposeBag() Observable.from(books) .take(while: { $0.count < 4 }) .subscribe (onNext: { book in print("내가 본 \(book)") }, onCompleted: { print("지식 충전 완료") }) .disposed(by: bag) /* 내가 본 데미안 지식 충전 완료 */
Swift
복사

take(until:)

다른 Observable에서 이벤트가 발생하기 전까지 이벤트를 방출
skip(until:)과는 반대로 다른 Observable에서 이벤트가 발생하면 더이상 이벤트를 방출하지 않습니다.
let hamster동무 = PublishSubject<String>() let trigger = PublishSubject<String>() let disposeBag = DisposeBag() hamster동무 .take(until: trigger) .subscribe(onNext: { work in print("일하자 햄스터 동무, 하자 \(work)") }).disposed(by: disposeBag) hamster동무.onNext("바느질") hamster동무.onNext("공장일") trigger.onNext("햄스터 동무!! 국기에 대한 경례를 하시게!!") hamster동무.onNext("코딩") /* 일하자 햄스터 동무, 하자 바느질 일하자 햄스터 동무, 하자 공장일 */
Swift
복사

takeLast

완료가 되면 입력한 개수만큼 이전의 이벤트가 방출
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10] let subject = PublishSubject<Int>() let disposeBag = DisposeBag() subject .takeLast(2) .subscribe { print($0) } .disposed(by: disposeBag) numbers.forEach { subject.onNext($0) } subject.onNext(11) subject.onCompleted() /* next(10) next(11) completed */
Swift
복사

Distinct Operators

distinctUntilChanged

연달아 나오는 중복 요소 무시
let disposeBag = DisposeBag() Observable.of("딸기", "당근", "당근", "수박", "수박", "메론", "수박") .distinctUntilChanged() .subscribe(onNext: { print($0) }) .disposed(by: disposeBag) /* 딸기 당근 수박 메론 수박 */
Swift
복사