RxSwift를 사용한 여러 코드를 구경하면서 본 연산자들을 구경해보고 비교해보자...
연산자 | 역할 | 주요 사용 사례 |
---|---|---|
withUnretained | self의 강한 참조 방지 | 메모리 누수 방지 |
do | 사이드 이펙트 추가 | 디버깅, 로깅, 상태 변경 |
filter | 조건에 맞는 값만 필터링 | 유효성 검사, 이벤트 조건부 처리 |
flatMapLatest | 최신 스트림만 유지 | 검색, API 요청 |
bind | UI와 스트림 연결 | UI 업데이트 |
Driver | UI 바인딩을 위한 특별한 Observable | 안전한 UI 데이터 처리 |
map | 스트림 값 변환 | 데이터 포맷팅, 계산 |
merge | 여러 스트림 결합 | 다중 이벤트 처리 |
combineLatest | 최신 값 조합 | 폼 유효성 검사, 상태 계산 |
takeUntil | 특정 조건까지 스트림 방출 | 작업 종료 |
observable
.withUnretained(self)
.subscribe(onNext: { (owner, value) in
owner.updateUI(with: value)
})
.disposed(by: disposeBag)
observable
.do(onNext: { value in
print("Value received: \(value)")
}, onError: { error in
print("Error occurred: \(error)")
}, onDispose: {
print("Stream disposed")
})
.subscribe()
.disposed(by: disposeBag)
데이터 흐름을 변경하지 않고 사이드 이펙트 추가나 주로 로깅, 디버깅, 상태 업데이트에 사용
observable
.filter { $0 > 10 }
.subscribe(onNext: { value in
print("Filtered value: \(value)")
})
.disposed(by: disposeBag)
특정 조건(Bool을 반환하는 조건문)에 맞는 값만 통과시키거나 유효한 입력이나 특정 상태를 걸러낼 때 사용
button.rx.tap
.flatMapLatest {
return apiService.fetchData() // 새 요청이 오면 이전 요청은 취소
}
.subscribe(onNext: { data in
print("Fetched data: \(data)")
})
.disposed(by: disposeBag)
새로운 값이 들어오면 이전 스트림을 취소하고 최신 스트림만 처리, 주로 API호출이나 검색 입력 같은 최신 상태만 필요한 작업에 유용
viewModel.output.text
.bind(to: label.rx.text)
.disposed(by: disposeBag)
데이터를 UI 요소에 직접 연결하거나 에러 처리가 필요하지 않은 UI 바인딩 작업에 적합
let driver = observable
.asDriver(onErrorJustReturn: "Default value")
driver
.drive(label.rx.text)
.disposed(by: disposeBag)
UI와 데이터를 연결할 때 추천, 에러가 발생해도 UI에 안전하게 기본값을 표시할 수 있음
observable
.map { $0 * 2 }
.subscribe(onNext: { value in
print("Mapped value: \(value)")
})
.disposed(by: disposeBag)
입력 값에서 출력 값을 계산하거나 변환할 때 사용, UI 요소에 표시할 데이터를 변환하는데 유용
Observable.merge(stream1, stream2)
.subscribe(onNext: { value in
print("Merged value: \(value)")
})
.disposed(by: disposeBag)
여러 스트림에서 방출된 이벤트를 단일 스트림으로 결합, ex) 여러 버튼의 클릭 이벤트를 처리할 때
Observable.combineLatest(textField1.rx.text.orEmpty, textField2.rx.text.orEmpty) { text1, text2 in
return "\(text1) \(text2)"
}
.subscribe(onNext: { combinedText in
print("Combined text: \(combinedText)")
})
.disposed(by: disposeBag)
모든 입력 스트림 중 하나가 변경될 때마다 모든 최신 값을 조합, 폼 유효성 검사나 복합 상태 계산에 유용
observable
.takeUntil(button.rx.tap)
.subscribe(onNext: { value in
print("Value until tap: \(value)")
})
.disposed(by: disposeBag)
주로 작업을 특정 시점에서 중단하거나 종료해야 할 때 사용
observable
.observe(on: MainScheduler.instance) // UI 작업이므로 MainScheduler에서 실행
.bind(to: label.rx.text)
.disposed(by: disposeBag)
특징 | bind | Driver |
---|---|---|
에러 처리 | 에러를 방출하며 직접 처리해야 함 | 에러를 방출하지 않음, 기본값 반환 |
스케줄러 | 별도로 스케줄러 지정 필요 | 항상 MainScheduler에서 동작 |
공유 | 기본적으로 공유되지 않음 | 자동으로 공유 (Hot Observable) |
사용 대상 | UI 및 비 UI 요소 | 주로 UI 요소 |
유연성 | 유연하며 다양한 상황에서 사용 가능 | UI 바인딩에 최적화 |
스트림 재사용 | 여러 구독 시 스트림이 재생성됨 | 스트림을 공유하여 재생성 방지 |
Driver는 Relay와 비슷하게 둘 다 RxCocoa에서 제공하는 주로 UI 관련 작업에서 안정적인 데이터 흐름을 제공하기 위해 사용되는 것 같다.