새소식

iOS/RxSwift

[RxSwift] TimeBasedOperator

  • -

replay : Observable이 항목을 방출하기 시작한 후 구독하더라도 모든 Observer가 동일한 방출 순서를 볼 수 있도록 보장

let helloMention = PublishSubject<String>()
let bird = helloMention.replay(1) // 개수

bird.connect()
helloMention.onNext("1. Hello")
helloMention.onNext("2. Hi")

bird.subscribe(onNext: {
    print($0)   // 2. Hi
})
.disposed(by: disposeBag)

helloMention.onNext("3. How are you") // 지나고 나면 무조건 출력

// 2. Hi
// 3. How are you

replayAll: 모든 요소를 방출함, 메모리 누수에 주의해야 함

let a = PublishSubject<String>()
let aThing = a.replayAll()
aThing.connect()

a.onNext("Hello")
a.onNext("A thing is mine")

aThing
    .subscribe(onNext: {
        print($0) // 지나간 이벤트 방출 이후에도 구독의 내용을 볼 수 있음
    })
    .disposed(by: disposeBag)

// Hello
// A thing is mine

buffer : Observable에서 방출하는 이벤트를 번들로 묶어서 묶음으로 방출

let source = PublishSubject<String>()

var count = 0
let timer = DispatchSource.makeTimerSource()

timer.schedule(deadline: .now() + 2, repeating: .seconds(1))
timer.setEventHandler(handler: {
    count += 1
    source.onNext("\(count)")
})
timer.resume()

source
    .buffer(timeSpan: .seconds(2),
            count: 2, // 최대 2개로 방출
            scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print($0) // 타이머
    })
    .disposed(by: disposeBag)

// []
// ["1", "2"]
// ["3", "4"]
// ["5", "6"]
// ["7", "8"]
// ["9", "10"]

window : Observable의 항목을 하나씩 방출

let maxObservableCount = 5
let makeTime = RxTimeInterval.seconds(2)

let window = PublishSubject<String>()
var windowCount = 0

let windowTimerSource = DispatchSource.makeTimerSource()
windowTimerSource.schedule(deadline: .now() + 2, repeating: .seconds(2))
windowTimerSource.setEventHandler(handler: {
    windowCount += 1
    window.onNext("\(windowCount)")
})
windowTimerSource.resume()

window
    .window(timeSpan: makeTime,
            count: maxObservableCount,
            scheduler: MainScheduler.instance)
    .flatMap{ windowObservable -> Observable<(index: Int, element: String)> in
        return windowObservable.enumerated()
    }
    .subscribe(onNext:{
        print("\($0.index)번째 Observable의 요소 \($0.element)")
    })
    .disposed(by: disposeBag)
    
// 0번째 Observable의 요소 1
// 0번째 Observable의 요소 2
// error(Sequence timeout.)
// 0번째 Observable의 요소 3
// 0번째 Observable의 요소 4

delaySubscription : 구독하는 시간을 지연시킴

let delaySource = PublishSubject<String>()

var delayCount = 0
let delayTimeSource = DispatchSource.makeTimerSource()
delayTimeSource.schedule(deadline: .now() + 2, repeating: .seconds(1))
delayTimeSource.setEventHandler(handler: {
    delayCount += 1 // delayCount
    delaySource.onNext("\(delayCount)")
})
delayTimeSource.resume()

delaySource
    .delaySubscription(.seconds(5), // 설정된 시간이 지난 시점부터 이벤트 발생
                       scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

delay :  Next 이벤트의 전달을 지연

let delaySubject = PublishSubject<Int>()

var delayCount = 0
let delayTimerSource = DispatchSource.makeTimerSource()
delayTimerSource.schedule(deadline: .now(), repeating: .seconds(1))
delayTimerSource.setEventHandler(handler: {
    delayCount += 1 // delayCount 지연
    delaySubject.onNext(delayCount)
})
delayTimerSource.resume()

delaySubject
    .delay(.seconds(3), // 시퀀스 자체를 설정 시간만큼 지연
           scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

interval :  주어진 시간에 따라 방출되는 Observable 생성

Observable<Int>
    .interval(.seconds(3), // 설정된 시간 간격으로 이벤트 발생
              scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

 

timer : 주어진 시간만큼 지난 후 개별적으로 반환되는 Observable 생성 

※ dueTime : 구독시작 Delay, period: 간격

Observable<Int>
    .timer(.seconds(5), // dueTime : 구독을 시작하는 delay값
           period: .seconds(2),
           scheduler: MainScheduler.instance)
    .subscribe(onNext: {
        print($0)
    })
    .disposed(by: disposeBag)

timeout : 제한시간을 지정할 때 사용, 아래 예시는 버튼을 5초 안에 누르지 않으면 에러 발생

let pushButton = UIButton(type: .system)
pushButton.setTitle("PUSH!", for: .normal)
pushButton.sizeToFit()

PlaygroundPage.current.liveView = pushButton

pushButton.rx.tap
    .do(onNext: {
        print("tap")
    })
    .timeout(.seconds(5), scheduler: MainScheduler.instance) // 시간초과 이후에는 error 방출
    .subscribe{print($0)}
    .disposed(by: disposeBag)

 

출처

패스트캠퍼스 | 30개 프로젝트로 배우는 iOS 앱개발 with Swift 초격차 패키지 Online
728x90

'iOS > RxSwift' 카테고리의 다른 글

[RxSwift] Combine Operator  (0) 2023.10.03
[RxSwift] Traits  (0) 2023.09.18
[RxSwift] Subject  (0) 2023.09.16
[RxSwift] Observable  (0) 2023.09.10
Contents

포스팅 주소를 복사했습니다

이 글이 도움이 되었다면 공감 부탁드립니다.