티스토리 뷰

Mobile/iOS

RxSwift, RxCocoa. Publish

out of coding 2021. 1. 3. 12:35

RxSwift에서는 Cold, Hot가 있습니다.

 

구독자가 생기는 순간에 흐름을 방출하는 Cold와

구독자가 생기지도 않았는데 흐름을 방출하는 Hot이 있습니다.

 

Hot은 뜨겁게 달궈져서 만들어지기 때문에 시작부터 방출하는것이고

Cold는 차갑게 얼어서 만들어지기 때문에 시작할때는 방출하지 않는것입니다.

추후에 subscribe를 만나게 되면 따뜻해지는것이지요.

 

그래서 우리는 Subject를 이용해서 구독 시점에 발생되던것을 구독과 상관없이 Hot 하게 만들수 있습니다.

 

예를 들어서 Network 통신을 하고 나서 값을 가져오는 다음과 같은 예제가 있다고 합시다.

API.requestMe()
    .observe(on: MainScheduler.instance)
    .subscribe(onNext: { value in
        print("1:", value)
    })
    .disposed(by: disposeBag)

자 그럼 이것은 흐름을 방출하지 않고 subscribe를 하는 대상이 생겼을때 방출하게 되겠죠.

이것이 바로 Cold한겁니다.

 

그럼 PublishRelay를 한번 볼까요?

초기에 값을 설정하지 못하지만 subscribe되고 난 다음에도 값을 받고 있죠.

이전의 값은 방출하여도 가져오질 못합니다.

let publishRelay = PublishRelay<Int>()

publishRelay.accept(1)

publishRelay
    .observe(on: MainScheduler.instance)
    .subscribe(onNext: { value in
        print("1:", value)
    })
    .disposed(by: disposeBag)

publishRelay.accept(2)

이런 예제가 있다고 할 경우에 어떻게 될까요?

답은 다음과 같아요.

1: 2

1: 1은 출력이 되지 않아요.

 

왜냐면 subscribe가 1을 넣기 전에 만들어지기 때문이죠.

그럼 이걸 BehaviorRelay로 만들면 어떻게 되는지 보겠습니다.

let relay = BehaviorRelay<Int>(value: 1)

relay
  .observe(on: MainScheduler.instance)
  .subscribe(onNext: { value in
    print("1:", value)
  })
  .disposed(by: disposeBag)

relay.accept(2)

이번에는 어떤까요?

1: 1
1: 2

초기값을 가지고 있는 값이 들어가게 됩니다.

let relay = BehaviorRelay<Int>(value: 1)

relay.accept(0)

relay
  .observe(on: MainScheduler.instance)
  .subscribe(onNext: { value in
    print("1:", value)
  })
  .disposed(by: disposeBag)

relay.accept(2)

중간에 값을 변경하면 다음과 같아지게 됩니다.

1: 0
1: 2

마지막 값을 가지고 있다가 subscribe되는 시점에 전달하게 되어 있습니다.

 

PublishRelay를 가지고 BehaviorRelay와 동일하게 만들어 보겠습니다.

let publishRelay = PublishRelay<Int>()
let behaviorRelay = publishRelay.replay(1)
behaviorRelay.connect().disposed(by: disposeBag)
pyblishRelay.accept(1)
publishRelay.accept(2)
publishRelay.accept(3)
publishRelay.accept(4)
        
behaviorRelay
  .subscribe(onNext: { value in
    print("1:", value)
  })
  .disposed(by: disposeBag)
        
publishRelay.accept(5)
publishRelay.accept(6)

어떻게 결과가 나올까요?

1: 4
1: 5
1: 6

그렇습니다. replay가 1이어서 이전에 가지고 있던 값중 마지막 것을 유지하고 있습니다.

그것과 이후에 발생하는 값들에 대해서도 모두 수신하고 있군요.

 

현업에서는 아무래도 초기값을 가지고 화면의 처리를 하다보니까

BehaviorRelay를 많이 쓰는거 같고 이런 부분들은 적절히 잘 사용하면 좋을거 같습니다.

 

추가로 ReplayRelay라는것도 제공을 하여 주는데요.

위에 예제 부분에서 replay 부분을 조정해서 받을수 있게 해줍니다.

위의 예제에서 replay 부분을 2로 넣은것과 동일한 결과 입니다.

let replayRelay = ReplayRelay<Int>.create(bufferSize: 2)
replayRelay.accept(1)
replayRelay.accept(2)
replayRelay.accept(3)
replayRelay.accept(4)

replayRelay
  .subscribe(onNext: { value in
    print("1:", value)
  })
  .disposed(by: disposeBag)

replayRelay.accept(5)
replayRelay.accept(6)

결과는 

1: 3
1: 4
1: 5
1: 6

3, 4가 버퍼에 들어가서 있을것이고 subscribe 이후이기 때문에 5, 6은 그냥 한개씩 나오게 됩니다.

댓글
공지사항
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2024/05   »
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 29 30 31
글 보관함