RxSwift Operator

준우·2024년 7월 15일
0

Swift 이야기

목록 보기
17/19
post-thumbnail

RxSwift 의 Operator 들을 사용방법들을 간단하게 살펴보자

Operator

map

  • Observable 이 방출하는 각 항목을 변환함
import RxSwift

let disposeBag = DisposeBag()

Observable.of(1, 2, 3)
    .map { $0 * 2 }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/// 출력결과
2
4
6

filter

  • Observable 이 방출하는 항목 중 특정 조건을 만족하는 항목만을 방출함
import RxSwift

let disposeBag = DisposeBag()

Observable.of(1, 2, 3, 4, 5)
    .filter { $0 % 2 == 0 }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/// 출력결과
2
4

flatMap

  • 각 항목을 Observable로 변환한 후, Observable 이 방출하는 항목들을 단일 Observable 로 병합함
import RxSwift

let disposeBag = DisposeBag()

let observable1 = Observable.of(1, 2)
let observable2 = Observable.of(3, 4)

observable1.flatMap { _ in
    return observable2
}.subscribe(onNext: {
    print($0)
}).disposed(by: disposeBag)

/// 출력 결과
3
4
3
4

concat

  • 여러 Observable 을 순차적으로 결합하여 하나의 Observable 로 만듭니다. 각 Observable 이 완료된 후에 다음 Observable 이 시작됨
import RxSwift

let disposeBag = DisposeBag()

let observable1 = Observable.of(1, 2, 3)
let observable2 = Observable.of(4, 5, 6)

Observable.concat([observable1, observable2])
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/// 출력결과
1
2
3
4
5
6

merge

  • 여러 Observable 을 병합하여 동시에 방출되는 항목들을 단일 Observable 로 만듬
import RxSwift

let disposeBag = DisposeBag()

let subject1 = PublishSubject<Int>()
let subject2 = PublishSubject<Int>()

Observable.of(subject1, subject2)
    .merge()
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

subject1.onNext(1)
subject2.onNext(2)
subject1.onNext(3)
subject2.onNext(4)

/// 출력결과
1
2
3
4

combineLatest

  • 두 개 이상의 Observable 에서 방출된 최신 항목들을 결합하여 방출함
import RxSwift

let disposeBag = DisposeBag()

let observable1 = BehaviorSubject(value: "Hello")
let observable2 = BehaviorSubject(value: "World")

Observable.combineLatest(observable1, observable2) { text1, text2 in
    return "\(text1) \(text2)"
}.subscribe(onNext: {
    print($0)
}).disposed(by: disposeBag)

observable1.onNext("Hi")
observable2.onNext("RxSwift")

/// 출력결과
Hello World
Hi World
Hi RxSwift

zip

  • 두 개 이상의 Observable 에서 방출된 항목들을 조합하여 결합된 항목을 방출함
    Observable 에서 동일한 인덱스의 항목들이 결합됨
import RxSwift

let disposeBag = DisposeBag()

let observable1 = Observable.of(1, 2, 3)
let observable2 = Observable.of("A", "B", "C")

Observable.zip(observable1, observable2) { number, letter in
    return "\(number) \(letter)"
}.subscribe(onNext: {
    print($0)
}).disposed(by: disposeBag)

/// 출력결과
1 A
2 B
3 C

scan

  • 초기값과 함께 누적 결과를 계산하며, 이전 결과를 이용해 새로운 값을 생성함.
    그리고 reduce 와 유사하지만, 중간 결과를 방출한다는 부분에서 차이가 있음
import RxSwift

let disposeBag = DisposeBag()

Observable.of(1, 2, 3, 4, 5)
    .scan(0) { accumulator, value in
        return accumulator + value
    }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/// 출력 결과
1
3
6
10
15

reduce

  • 초기값과 함께 누적 결과를 계산하지만, 최종 결과만 방출함
import RxSwift

let disposeBag = DisposeBag()

Observable.of(1, 2, 3, 4, 5)
    .reduce(0) { accumulator, value in
        return accumulator + value
    }
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/// 출력 결과
15

distinctUntilChanged

  • 이전 항목과 동일한 항목을 무시하고 고유한 항목만 방출함
import RxSwift

let disposeBag = DisposeBag()

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

/// 출력 결과
1
2
3
4
5

take

  • Observable 이 방출하는 처음 N개의 항목만 방출함
import RxSwift

let disposeBag = DisposeBag()

Observable.of(1, 2, 3, 4, 5)
    .take(3)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/// 출력 결과
1
2
3

skip

  • Observable 이 방출하는 처음 N개의 항목을 무시하고, 그 이후의 항목을 방출함
import RxSwift

let disposeBag = DisposeBag()

Observable.of(1, 2, 3, 4, 5)
    .skip(2)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

/// 출력 결과
3
4
5

takeUntil

  • 두 번째 Observable 이 항목을 방출할 때까지 첫 번째 Observable 에서 항목을 방출함
import RxSwift

let disposeBag = DisposeBag()
let stopObservable = PublishSubject<Void>()

Observable.of(1, 2, 3, 4, 5)
    .takeUntil(stopObservable)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// 두 번째 Observable이 방출되면서 첫 번째 Observable의 방출이 중단됩니다.
stopObservable.onNext(())

/// 출력 결과
/// stopObservable.onNext(())가 호출되는 시점에 따라 출력 결과가 달라질 수 있음.
1 or 1 2 3

withLatestFrom

  • 기준 Observable 의 항목과 다른 Observable 에서 가장 최근에 방출된 항목을 결합함
import RxSwift

let disposeBag = DisposeBag()
let buttonTap = PublishSubject<Void>()
let textFieldInput = PublishSubject<String>()

buttonTap
    .withLatestFrom(textFieldInput)
    .subscribe(onNext: {
        print("Button tapped with text: \($0)")
    })
    .disposed(by: disposeBag)

textFieldInput.onNext("Hello")
buttonTap.onNext(())
textFieldInput.onNext("World")
buttonTap.onNext(())

/// 출력 결과
Button tapped with text: Hello
Button tapped with text: World

debounce

  • 지정된 시간 동안 새로운 항목이 방출되지 않을 때까지 대기한 후, 가장 최근 항목을 방출함
  • 주로 검색기능에서 많이 사용됨
import RxSwift

let disposeBag = DisposeBag()

Observable.of(1, 2, 3, 4, 5)
    .debounce(.milliseconds(500), scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

// 방출 시간 간격이 짧아서 모든 항목이 출력되지 않을 수 있습니다.

throttle

  • 지정된 시간 간격 동안 Observable 이 방출하는 항목 중 첫 번째 항목만 방출하고, 이후에는 해당 시간 간격 동안 방출된 항목들을 무시함
import RxSwift
import RxCocoa

let disposeBag = DisposeBag()

// 버튼 클릭 이벤트를 시뮬레이션하기 위한 PublishSubject 생성
let buttonTap = PublishSubject<Void>()

// 1초 동안 한 번만 이벤트를 방출하도록 throttle 적용
buttonTap
    .throttle(.seconds(1), scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print("Button tapped")
    })
    .disposed(by: disposeBag)

// 버튼 클릭 시뮬레이션
buttonTap.onNext(())
buttonTap.onNext(())
buttonTap.onNext(())
DispatchQueue.main.asyncAfter(deadline: .now() + 1.5) {
    buttonTap.onNext(())
}

/// 출력 결과
Button tapped
Button tapped

0개의 댓글