Scheduler는 RxSwift에서 작업이 실행되는 스레드나 큐를 관리하는 역할을 한다.
Observable 구독을 통해서 UI 작업을 처리하게 되었다면, 그 작업이 메인 스레드에서 동작하도록 명시하는 것이 좋다.
( “UI 작업은 메인 스레드에서 이루어져아한다” → iOS 앱 개발의 기본 개념 )
Observable.just("Hello")
.observeOn(MainScheduler.instance)
.subscribe(onNext: { value in
print(value) // UI 업데이트
})let scheduler = ConcurrentDispatchQueueScheduler(qos: .background)
Observable.just("Background Task")
.subscribeOn(scheduler)
.observeOn(MainScheduler.instance)
.subscribe(onNext: { value in
print(value)
})userInteractive (최고 우선순위 - e.g. UI 업데이트 ,애니메이션)userInitiated (높은 우선순위 - e.g. 버튼 클릭 후 데이터 로딩)default (기본 우선순위 - e.g. 일반적인 백그라운드 작업)utility (낮은 우선순위 - e.g. 데이터 다운로드, 백업)background (최저 우선순위 - e.g. 대용량 데이터 정리, 동기화)unspecified (시스템 결정 - 어떤 우선순위로 처리해도 상관없는 작업)let queue = DispatchQueue(label: "com.example.serial")
let scheduler = SerialDispatchQueueScheduler(queue: queue, internalSerialQueueName: "serialQueue")
Observable.of(1, 2, 3)
.subscribeOn(scheduler)
.subscribe(onNext: { value in
print(value)
})subscribeOn & observeOnsubscribeOn: Observable이 구독될 때 사용할 스레드를 지정한다. observeOn: Observable이 방출하는 이벤트를 처리할 스레드를 지정한다.| https://reactivex.io/documentation/scheduler.html |
|---|
![]() |
예제:
Observable.of(1, 2, 3)
.subscribeOn(ConcurrentDispatchQueueScheduler(qos: .background)) // Observable 생성 시 백그라운드 스레드 사용
.observeOn(MainScheduler.instance) // UI 업데이트는 메인 스레드에서 실행
.subscribe(onNext: { value in
print(value)
})
Subject는 Observable과 Observer의 역할을 동시에 하는 특별한 타입이다.
| https://reactivex.io/documentation/subject.html |
|---|
![]() |
let subject = BehaviorSubject(value: "Initial Value")
subject.onNext("Second Value")
subject.subscribe(onNext: { value in
print(value)
})| https://reactivex.io/documentation/subject.html |
|---|
![]() |
let subject = PublishSubject<String>()
subject.onNext("Ignored")
subject.subscribe(onNext: { value in
print(value)
})
subject.onNext("Emitted")Relay는 RxCocoa에서 제공하며, 에러나 완료를 방출하지 않고 UI 중심 작업에서 주로 사용된다.
.accept() 메서드로 값을 방출, 에러 방출 불가.let relay = BehaviorRelay(value: "Initial Value")
relay.accept("Updated Value")
relay.asObservable()
.subscribe(onNext: { value in
print(value)
})let relay = PublishRelay<String>()
relay.accept("Event 1")
relay.asObservable()
.subscribe(onNext: { value in
print(value)
})
relay.accept("Event 2")let button = UIButton()
button.rx.tap
.subscribe(onNext: {
print("Button tapped")
})
.disposed(by: disposeBag)
let textField = UITextField()
textField.rx.text.orEmpty
.bind(to: viewModel.inputText)
.disposed(by: disposeBag)
Rx를 활용해서 버튼을 클릭했을 때 랜덤한 정수를 생성하고,
생성된 정수가 짝수면 버튼의 색상이 초록색,
생성된 정수가 홀수면 버튼의 색상이 빨간색으로 바뀌는 로직을 작성하고 싶어.
이때 버튼의 중복 클릭이나 과도한 연속 클릭을 방지하기 위해throttle도 적용할거야.
import UIKit
import SnapKit
import RxSwift
import RxCocoa
struct MyError: Error {}
let ioScheduler = SerialDispatchQueueScheduler(qos: .default)
class ViewController: UIViewController {
let disposeBag = DisposeBag()
let button: UIButton = {
let button = UIButton()
button.backgroundColor = .blue
button.setTitle("버튼", for: .normal)
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
initUI()
bind()
}
func initUI() {
view.backgroundColor = .white
[button].forEach { view.addSubview($0) }
button.snp.makeConstraints {
$0.width.equalTo(120)
$0.height.equalTo(80)
$0.center.equalToSuperview()
}
}
func bind() {
button.rx.tap
.throttle(.seconds(2), scheduler: MainScheduler.instance)
.map { [weak self] in
guard let self else { throw MyError() }
return getRandomInt().isEvenNumber()
}
.subscribe(on: ioScheduler)
.observe(on: MainScheduler.instance)
.subscribe(onNext: { [weak self] isEvenNumber in
guard let self else { return }
if isEvenNumber {
button.backgroundColor = .green
} else {
button.backgroundColor = .red
}
}).disposed(by: disposeBag)
}
/// 1부터 10 중에 랜덤한 정수를 얻는 함수.
///
/// - Returns: 랜덤 정수.
func getRandomInt() -> Int {
let randomNumber = Int.random(in: 1...10)
print("랜덤 정수: \(randomNumber)")
return randomNumber
}
}
extension Int {
/// 파라미터로 들어온 정수가 짝수인지 판별하는 함수,
///
/// - Parameter number: 판별할 정수.
/// - Returns: 짝수면 true, 홀수면 false.
func isEvenNumber() -> Bool {
self % 2 == 0
}
}