Filtering Operator

DEVJUN·2024년 3월 13일
0

RxSwift

목록 보기
5/7
post-thumbnail

이번 포스팅에선 Observable을 필터링 할 수 있는 연산자들에 대해 알아봅시다~!

1. ignoreElements(next 이벤트는 모두 무시하고 Completed 이벤트나 Error 이벤트만 전달하는 연산자)

let disposeBag = DisposeBag()
let fruits = ["🍏", "🍎", "🍋", "🍓", "🍇"]

Observable.from(fruits)
    .ignoreElements()
    .subscribe { print($0) }
    .disposed(by: disposeBag)
    
===============================================
결과
Completed

2. elementAt(특정 인덱스에 위치한 요소만 구독자로 전달하는 연산자)

let disposeBag = DisposeBag()
let fruits = ["🍏", "🍎", "🍋", "🍓", "🍇"]

Observable.from(fruits)
    .element(at: 1)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

===============================================
결과
next(🍎)
Completed

3. filter(특정 조건에 맞는 항목을 구독자로 전달하는 연산자)

let disposeBag = DisposeBag()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Observable.from(numbers)
    .filter { $0.isMultiple(of: 2) }
    .subscribe { print($0) }
    .disposed(by: disposeBag)

===============================================
결과
next(2)
next(4)
next(6)
next(8)
next(10)
completed

4. skip(지정한 수만큼 next 이벤트를 무시하는 연산자)

let disposeBag = DisposeBag()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Observable.from(numbers)
    .skip(3)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

===============================================
결과
next(4)
next(5)
next(6)
next(7)
next(8)
next(9)
next(10)
completed    

5. skip(until:) (트리거가 이벤트를 방출한 이후에 새롭게 방출된 이벤트만 구독자로 전달하는 연산자)

let disposeBag = DisposeBag()

let subject = PublishSubject<Int>()
let trigger = PublishSubject<Int>()

subject.skip(until: trigger)
    .subscribe { print($0) }
    .disposed(by: disposeBag)


subject.onNext(1)

trigger.onNext(0)

subject.onNext(2)

===============================================
결과
next(2)

6. skip(while:) (filter와 달리 클로저가 한번이라도 false를 리턴하면 조건을 판단하지 않는 연산자)

let disposeBag = DisposeBag()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Observable.from(numbers)
    .skip(while: { !$0.isMultiple(of: 2) })
    .subscribe { print($0) }
    .disposed(by: disposeBag)

===============================================
결과
next(2)
next(3)
next(4)
next(5)
next(6)
next(7)
next(8)
next(9)
next(10)
completed

7. skip(duration:scheduler:) (지정한 시간동안 이벤트 방출을 무시하는 연산자)

let disposeBag = DisposeBag()

let o = Observable<Int>.interval(.seconds(1), scheduler: MainScheduler.instance)

o.take(10)
    .skip(.seconds(3), scheduler: MainScheduler.instance)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

===============================================
결과
next(2)
next(3)
next(4)
next(5)
next(6)
next(7)
next(8)
next(9)
completed

8. take (정수를 파라미터로 받아 해당 숫자 만큼 이벤트 방출하는 연산자)

let disposeBag = DisposeBag()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Observable.from(numbers)
    .take(5)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

===============================================
결과
next(1)
next(2)
next(3)
next(4)
next(5)
completed

9. take(while:)
조건을 충족하는 동안 이벤트를 방출하는 연산자,
inclusive인 경우 조건에 걸리는 마지막 값까지 전달

let disposeBag = DisposeBag()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Observable.from(numbers)
    .take(while: { !$0.isMultiple(of: 2) }, behavior: .inclusive)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

===============================================
결과
next(1)
next(2)
completed



let disposeBag = DisposeBag()
let numbers = [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]

Observable.from(numbers)
    .take(while: { !$0.isMultiple(of: 2) }, behavior: .exclusive)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

===============================================
결과
next(1)
completed

10. take(until:) (트리거 옵저버블이 next 이벤트를 방출하기 전까지 이벤트를 방출하는 연산자 -> 트리거에서 요소를 방출하면 completed 이벤트가 방출됨)

let disposeBag = DisposeBag()

let subject = PublishSubject<Int>()
let trigger = PublishSubject<Int>()

subject.take(until: trigger)
    .subscribe { print($0) }
    .disposed(by: disposeBag)

subject.onNext(1)
subject.onNext(2)

trigger.onNext(0)

subject.onNext(3)

===============================================
결과
next(1)
next(2)
completed

11. takeLast (onCompleted시에 마지막으로 방출되는 count개의 요소가 구독자로 전달하는 연산자)

let disposeBag = DisposeBag()

let subject = PublishSubject<Int>()

subject.takeLast(2)
    .subscribe { print($0) }
    .disposed(by: disposeBag)


(1...10).forEach { subject.onNext($0) }

subject.onNext(11)

subject.onCompleted()

enum MyError: Error {
    case error
}

subject.onError(MyError.error)

===============================================
결과
next(10)
next(11)
completed

12. distinctUntilChanged (동일한 요소가 연속적으로 방출되는 것을 막아주는 연산자)

struct Person {
    let name: String
    let age: Int
}

let disposeBag = DisposeBag()
let persons = [
    Person(name: "Sam", age: 12),
    Person(name: "Paul", age: 12),
    Person(name: "Tim", age: 56)
]

Observable.from(persons)
    .distinctUntilChanged(at: \.age)
    .subscribe { print($0) }
    .disposed(by: disposeBag)


===============================================
결과
next(Person(name: "Sam", age: 12))
next(Person(name: "Tim", age: 56))
completed

13. debounce, throttle (동일한 요소가 연속적으로 방출되는 것을 막아주는 연산자)

// 짧은 시간동안 반복적으로 방출되는 이벤트 제어

// next 이벤트가 전달된 다음 지정된 시간이 경과하기까지 다른 이벤트가 전달되지 않는다면 마지막에 방출한 이벤트를 구독자에게 전달함
// (검색 기능 구현시 사용 사용자가 키워드를 검색할 때마다 네트워크 요청을 하거나 데이터베이스를 검색하는 경우 문자가 입력될때마다 매번 검색은 효율적이지 않음 -> 사용자가 문자를 연속적으로 입력할 때 호출하는 것은 효율적이지 않음 지정된 시간동안 문자를 입력하지 않으면 그때 네트워크 요청)

let disposeBag = DisposeBag()

let buttonTap = Observable<String>.create { observer in
   DispatchQueue.global().async {
      for i in 1...10 {
         observer.onNext("Tap \(i)")
         Thread.sleep(forTimeInterval: 0.3)
      }
      
      Thread.sleep(forTimeInterval: 1)
      
      for i in 11...20 {
         observer.onNext("Tap \(i)")
         Thread.sleep(forTimeInterval: 0.5)
      }
      
      observer.onCompleted()
   }
   
   return Disposables.create {
       
   }
}

// 지정된 시간동안 새로운 이벤트가 방출되지 않으면 가장 마지막에 방출된 이벤트를 구독자에게 전달함
buttonTap
    .debounce(.milliseconds(1000), scheduler: MainScheduler.instance)
    .subscribe { print($0) }
    .disposed(by: disposeBag)


===============================================
결과
next(Tap 10)
next(Tap 20)
completed





// 지정된 주기마다 하나씩 구독자에게 next 이벤트 전달 (짧은 시간 발생하는 버튼 탭과 delegate 메시지 처리시 사용)

let disposeBag = DisposeBag()

let buttonTap = Observable<String>.create { observer in
   DispatchQueue.global().async {
      for i in 1...10 {
         observer.onNext("Tap \(i)")
         Thread.sleep(forTimeInterval: 0.3)
      }
      
      Thread.sleep(forTimeInterval: 1)
      
      for i in 11...20 {
         observer.onNext("Tap \(i)")
         Thread.sleep(forTimeInterval: 0.5)
      }
      
      observer.onCompleted()
   }
   
   return Disposables.create {
      
   }
}

buttonTap    
    .throttle(.milliseconds(1000), scheduler: MainScheduler.instance)
    .subscribe { print($0) }
    .disposed(by: disposeBag)




===============================================
결과
next(Tap 1)
next(Tap 4)
next(Tap 7)
next(Tap 10)
next(Tap 11)
next(Tap 12)
next(Tap 14)
next(Tap 16)
next(Tap 18)
next(Tap 20)
completed



KXCoding 강의
Marble Diagram
ReactiveX 사이트

profile
🧑🏻‍💻iOS

0개의 댓글