[RxSwift] BehaviorRelay, BehaviorSubject 활용

김상우·2022년 7월 2일
0

ref : https://joycestudios.tistory.com/88


Relay vs Subject

  • 공통점

Observable 의 역할과 Observer 의 역할을 모두 할 수 있다.

  • 차이점
  1. RelayRxCocoa 의 클래스, SubjectRxSwift 내의 클래스다.
  1. Subject 는 .completed, .error 등의 이벤트가 발생하면 subscribe 가 종료된다. Relay 객체는 .completed, .error 등을 발생시키지 않고 Dispose 되기 전까지 계속 동작하기 때문에 UI 작업에서 사용하기 용이하다. RxCocoa 에 포함 되어있다는것 자체도 UI 작업을 위한 클래스라는 것을 의미하기도한다.
  1. Subject 에서의 값 입력 : mySubject.onNext( x )
    값 출력 : mySubject.subscribe { value in ... }
    Relay 에서의 값 입력 : myRelay.accept( x )
    값 출력 : myRelay.value

Publish vs Behavior

  • PublishSubject, BehaviorSubject, ReplaySubject 등이 있지만 난 현재 Publish 와 Behavior 를 가장 자주 쓰고있다. 그래서 이 둘을 비교해서 기록한다. 그리고 PublishSubject 의 개념은 PublishRelay 에도 적용해서 이해할 수 있다.

  • 쉬운 결론부터 내리자면, 둘의 차이점은 초기값이 있냐 없냐로 구분 지을 수 있다.


Publish

  1. 초기값이 없다.
  2. 구독을 한 뒤로 발행하는 모든 값들에 반응한다.

Behavior

  1. 초기값이 있다. x 라는 초기값을 가지고, 값을 발행받기 전이라면 x 라는 값으로 대체해서 사용한다. 그 뒤로 구독을 하는 구독자는 가장 최근의 값을 초기값으로 가진다.
  2. 구독을 한 뒤로 발행하는 모든 값에 반응한다.

MVVM 패턴 코드 비교

ViewController 의 UILabel 에 서버에서 가져온 텍스트를 띄워줘야 하는 상황이라고 할 때, 각각 다음과 같은 코드를 작성할 수 있다.


BehaviorSubject 를 사용한 코드

  • ViewModel.swift
let textSubject = BehaviorSubject<String>(value: "...")

// RxMoya
moyaProvider.rx.request(.getLabelText())
	.map(entity.self)
	.subscribe(onSuccess: {[weak self] result in 
  		self?.textSubject.onNext(result)
  	}, onFailure: { [weak self] error in 
  		print(error)
  	}).disposed(by: bag)
  • ViewController.swift
var myLabel = UILabel()
// viewModel binding
viewModel.textSubject.subscribe(on: MainScheduler.instance)
  	.bind { [weak self] text in 
  		self.myLabel.text = text
	}.disposed(by: bag)

// 현재 뷰모델이 가진 텍스트를 출력하고 싶은 경우 -> 다시 구독을 해줘야 함
viewModel.textSubject.bind { [weak self] text in 
  		print(text)
	}.disposed(by: bag)

BehaviorRelay 를 사용한 코드

  • ViewModel.swift
let textRelay = BehaviorRelay<String>(value: "...")

// RxMoya
moyaProvider.rx.request(.getLabelText())
  	.map(entity.self)
  	.subscribe(onSuccess: {[weak self] result in
  		self?.textRelay.accept(result)
  	}, onFailure: {[[weak self] error in 
  		print(error)
  	}).disposed(by: bag)

  • ViewController.swift
var myLabel = UILabel()
// viewModel binding
viewModel.textRelay.subscribe(on: MainScheduler.instance)
  	.bind { [weak self] text in 
  		self.myLabel.text = text
  	}.disposed(by: bag)

// 현재 뷰모델이 가진 텍스트를 출력하고 싶은 경우 -> 구독 과정을 거치지 않아도 됨
print(viewModel.textRelay.value)
profile
안녕하세요, iOS와 알고리즘에 대한 글을 씁니다.

0개의 댓글