일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | ||||||
2 | 3 | 4 | 5 | 6 | 7 | 8 |
9 | 10 | 11 | 12 | 13 | 14 | 15 |
16 | 17 | 18 | 19 | 20 | 21 | 22 |
23 | 24 | 25 | 26 | 27 | 28 |
- swift db
- ios
- RxSwift
- GCD
- Swift Tuist
- swift 5.9
- arc
- swiftdata
- Tuist Swift
- Subscribe
- ribs
- 네트워크 통신
- JSON
- SeSAC
- ios database
- swift 6
- swift
- xcode
- realm
- KeyPath
- observable
- 카카오뱅크 ios
- Subject
- Firebase
- SwiftUI
- swift database
- ios swiftdata
- Tuist
- Combine
- Firebase Analytics
- Today
- Total
천원의 개발
RxSwift Operator 정리 본문
안녕하세요. 천원입니다.
RxSwift를 사용하면서 너무 데이터 바인딩의 목적으로만 사용하는 것 같아 반성하고자 다양한 오퍼레이터들을 정리 해보려고 합니다. 자주 사용하는 오퍼레이터들은 별표를 붙여두었습니다.
Transforming Observables
- map ☆
옵저버블의 각 항목을 변환하여 새로운 항목을 생성합니다.
Observable.of(1, 2, 3)
.map {
$0 * 2
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 2, 4, 6 출력
- flatMap
옵저버블의 항목을 다른 옵저버블로 변환하고 병합합니다.
Observable.of(1, 2, 3)
.flatMap {
Observable.of($0 * 2, $0 * 4)
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 2, 4, 4, 8, 6, 12 출력
map은 주로 각 항목을 일대일 매핑을 할 때 사용되고, flatMap은 각 항목을 다른 옵저버블로 매핑하고 비동기로 처리한 작업을 병합하기 때문에 비동기 작업에 적합합니다.
- scan
시퀀스의 각 항목에 대해 누적된 결과를 생성합니다.
Observable.of(1, 2, 3, 4, 5)
.scan(0) { accumulated, value in
return accumulated + value
}
.subscribe(onNext: { value in
print(value)
})
.disposed(by: disposeBag)
// 1, 3, 6, 10, 15 출력
0을 초기값으로 반환하는 값들을 누적해서 처리합니다.
Filtering Observables
- filter
주어진 조건을 만족하는 옵저버블 한목만 유지합니다.
Observable.of(1, 2, 3, 4)
.filter {
$0 % 2 == 0
}
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 2, 4 출력
- distinctUntilChanged ☆
연속적으로 중복된 항목을 필터링합니다.
Observable.of(1, 1, 1, 2, 3)
.distinctUntilChanged()
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 1, 2, 3 출력
우리가 Observable 활용하여 API 호출을 할 때 중복 호출을 방지할 수 있습니다.
- skip & take
'skip' 지정된 개수의 항목을 건너뜁니다. 'take' 지정된 개수의 항목만 유지합니다.
Observable.of(1, 2, 3, 4, 5)
.skip(2)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 3, 4, 5 출력
Observable.of(1, 2, 3, 4, 5)
.take(2)
.subscribe(onNext: {
print($0)
})
.disposed(by: disposeBag)
// 1, 2 출력
- throttle ☆
지정한 시간동안 처음 들어오는 이벤트를 방출합니다.
-> 처음 들어오는 이벤트 외 일정시간 동안 뒤에 들어오는 이벤트는 무시
button.rx.tap
.throttle(.seconds(1), scheduler: MainScheduler.instance)
.bind {
print("tap")
}
.disposed(by: disposeBag)
// 1초동안 500번 tap해도 처음 입력한 tap에만 반응한다.
버튼의 중복 입력을 막는데 효율적인 오퍼레이터입니다.
- debounce
throttle과 비슷하지만 지정한 시간동안 들어오는 이벤트 중 마지막 이벤트를 방출합니다.
-> 특정 시간 동안 이벤트가 들어오면 마지막 이벤트만 실행하고 나머지는 무시
button.rx.tap
.debounce(.seconds(1), scheduler: MainScheduler.instance)
.bind {
print("tap")
}
.disposed(by: disposeBag)
// 1초동안 500번 tap해도 마지막 이벤트만 반응
Combining Observables
- combineLatest ☆
여러 개의 옵저버블로부터 최신 값을 결합합니다.
let bird = PublishSubject<String>()
let mammal = PublishSubject<String>()
Observable.combineLatest( bird, mammal)
.subscribe(onNext: { bird, mammal in
print("\(bird) + \(mammal)")
})
.disposed(by: disposeBag)
bird.onNext("잉꼬")
mammal.onNext("호랑이")
bird.onNext("참새")
bird.onNext("까치")
mammal.onNext("사자")
// 잉꼬 + 호랑이, 참새 + 호랑이, 까치 + 호랑이, 까치 + 사자 출력
중요한 점은 둘 중 하나의 subject에서 이벤트를 방출해도 동작한다는 점입니다. 최초 잉꼬는 mammal Subject에 방출한 이벤트가 없어서 동작하지 않았습니다.
- zip
두 개의 옵저버블을 병렬로 결합합니다.
let bird = PublishSubject<String>()
let mammal = PublishSubject<String>()
Observable.zip( bird, mammal)
.subscribe(onNext: { bird, mammal in
print("\(bird) + \(mammal)")
})
.disposed(by: disposeBag)
bird.onNext("잉꼬")
mammal.onNext("호랑이")
bird.onNext("참새")
bird.onNext("까치")
mammal.onNext("사자")
// 잉꼬 + 호랑이, 참새 + 사자 출력
자신의 짝이 와야 출력합니다. 잉꼬는 호랑이가 들어왔으니 출력하였고 참새는 기다렸다가 사자가 들어왔을 때 출력하였습니다. 까치는 짝이 들어오지 않아서 출력하지 않았네요
- merge
여러개의 옵저버블을 하나의 옵저버블로 만듭니다.
let bird = PublishSubject<String>()
let mammal = PublishSubject<String>()
Observable.merge( bird, mammal)
.subscribe(onNext: { animal in
print(animal)
})
.disposed(by: disposeBag)
bird.onNext("잉꼬")
mammal.onNext("호랑이")
bird.onNext("참새")
bird.onNext("까치")
mammal.onNext("사자")
// 잉꼬, 호랑이, 참새, 까치, 사자 출력
- withLatestFrom ☆
두 개의 옵저버블을 조합하고, 하나의 옵저버블의 최신 값을 사용하여 다른 옵저버블을 변환하는 데 사용합니다.
무슨말이지 어려우니까 코드로 보여드릴게요.
let bird = PublishSubject<String>()
button.rx.tap
.withLatestFrom(bird)
.subscribe(onNext: { name in
let greeting = "Hello, \(name)!"
print(greeting)
})
.disposed(by: disposeBag)
bird.onNext("잉꼬")
DispatchQueue.main.asyncAfter(deadline: .now() + 3) {
bird.onNext("앵무새")
}
DispatchQueue.main.asyncAfter(deadline: .now() + 6) {
bird.onNext("참새")
}
// 잉꼬 출력 -> 앵무새 출력 -> 참새 출력
버튼을 누를 때 마다 가장 최근에 들어온 bird 이벤트를 출력합니다. 정리하자면 하나의 옵저버블이 새로운 이벤트가 들어 올 때 withLatestFrom에 넣어둔 옵저버블의 최신 이벤트를 사용해서 동작하는 겁니다. 그러니 bird 이벤트가 아무리 들어와도 출력은 안 되겠죠.
'iOS&Swift🍎 > RxSwift' 카테고리의 다른 글
RxSwift Subscribe, Bind, Drive 차이점 (0) | 2022.10.28 |
---|---|
RxSwift Observable vs Subject(Publish, Behavior) 차이점 (0) | 2022.10.27 |
RxSwift 개념 정리 (Observable, Disposable) (0) | 2022.10.26 |