Swift - RxSwift: Subject와 Relay

2 분 소요


ReactiveX Subject 문서 참고


Subject는 Observer && Observable

  • Observer
    • 하나 이상의 Observable을 구독할 수 있음
    • 원래 Cold Observable를 Hot Observable로 변경하는 효과 보임
    • Hot & Cold
  • Observable
    • event emit 가능

PublishSubject

Untitled

  • subscribe했을 때 이벤트
    • 값이 업데이트될 때마다
    • 에러
    • subject가 종료 되었을 때
              let publishSubject = PublishSubject<Int>()
        
              let subscribe1 = publishSubject
                  .subscribe(onNext: { (num) in
                      print("subscribe1 :", num)
                  }, onError: { (error) in
                      print("subscribe1 Erorr: ", error)
                  }, onCompleted: {
                      print("subscribe1 onCompleted")
                  })
        
              publishSubject.onNext(1)
              publishSubject.onNext(2)
        
              let subscribe2 = publishSubject
                  .subscribe(onNext: { (num) in
                      print("subscribe2 :", num)
                  }, onError: { (error) in
                      print("subscribe2 Erorr: ", error)
                  }, onCompleted: {
                      print("subscribe2 onCompleted")
                  })
        
              publishSubject.onNext(3)
        
              publishSubject.onCompleted() // 종료
        
              publishSubject.onNext(4)
              publishSubject.onNext(5)
    
       subscribe1 : 1
       subscribe1 : 2
       subscribe1 : 3
       subscribe2 : 3
       subscribe1 onCompleted
       subscribe2 onCompleted
    

BehaviorSubject: 초기값이 있는 PublishSubject

Untitled

  • 처음 subscribe하면 초기값 또는 직전의 값 들고 옴

              let behaviorSubject = BehaviorSubject<Int>(value: 0)
        
              let subscribe1 = behaviorSubject
                  .subscribe(onNext: { (num) in
                      print("subscribe1 :", num)
                  }, onError: { (error) in
                      print("subscribe1 Erorr: ", error)
                  }, onCompleted: {
                      print("subscribe1 onCompleted")
                  })
        
              behaviorSubject.onNext(1)
              behaviorSubject.onNext(2)
        
              let subscribe2 = behaviorSubject
                  .subscribe(onNext: { (num) in
                      print("subscribe2 :", num)
                  }, onError: { (error) in
                      print("subscribe2 Erorr: ", error)
                  }, onCompleted: {
                      print("subscribe2 onCompleted")
                  })
        
              behaviorSubject.onNext(3)
        
              behaviorSubject.onCompleted() // 종료
        
              behaviorSubject.onNext(4)
              behaviorSubject.onNext(5)
    
      subscribe1 : 0 // 초기값 0
      subscribe1 : 1
      subscribe1 : 2
      subscribe2 : 2 // 직전 값 2
      subscribe1 : 3
      subscribe2 : 3
      subscribe1 onCompleted
      subscribe2 onCompleted
    

ReplaySubject

Untitled

  • bufferSize만큼 저장해 두었다가, subscribe하면 저장해 둔 최신 값들 반환

              let replaySubject = ReplaySubject<Int>.create(bufferSize: 3)
              // 모든 이벤트 저장: .createUnbounded()
        
              let subscribe1 = replaySubject
                  .subscribe(onNext: { (num) in
                      print("subscribe1 :", num)
                  }, onError: { (error) in
                      print("subscribe1 Erorr: ", error)
                  }, onCompleted: {
                      print("subscribe1 onCompleted")
                  })
        
              replaySubject.onNext(1)
              replaySubject.onNext(2)
        
              let subscribe2 = replaySubject
                  .subscribe(onNext: { (num) in
                      print("subscribe2 :", num)
                  }, onError: { (error) in
                      print("subscribe2 Erorr: ", error)
                  }, onCompleted: {
                      print("subscribe2 onCompleted")
                  })
        
              replaySubject.onNext(3)
        
              replaySubject.onCompleted() // 종료
        
              replaySubject.onNext(4)
              replaySubject.onNext(5)
    
      subscribe1 : 1
      subscribe1 : 2
      subscribe2 : 1 // 버퍼에 있던 최신값 1
      subscribe2 : 2 // 버퍼에 있던 최신값 2
      subscribe1 : 3
      subscribe2 : 3
      subscribe1 onCompleted
      subscribe2 onCompleted
    

AsyncSubject

Untitled

  • complete가 되면 이벤트 발생 후 종료

              let asyncSubject = AsyncSubject<Int>()
        
              let subscribe1 = asyncSubject
                  .subscribe(onNext: { (num) in
                      print("subscribe1 :", num)
                  }, onError: { (error) in
                      print("subscribe1 Erorr: ", error)
                  }, onCompleted: {
                      print("subscribe1 onCompleted")
                  })
        
              asyncSubject.onNext(1)
              asyncSubject.onNext(2)
        
              let subscribe2 = asyncSubject
                  .subscribe(onNext: { (num) in
                      print("subscribe2 :", num)
                  }, onError: { (error) in
                      print("subscribe2 Erorr: ", error)
                  }, onCompleted: {
                      print("subscribe2 onCompleted")
                  })
        
              asyncSubject.onNext(3)
        
              asyncSubject.onCompleted() // 종료
        
              asyncSubject.onNext(4)
              asyncSubject.onNext(5)
    
      subscribe1 : 3
      subscribe2 : 3
      subscribe1 onCompleted
      subscribe2 onCompleted
    

Relay

  • PublishRelay,  BehaviorRelayReplayRelay
  • RxCocoa의 클래스
  • .accept()로 이벤트 방출

              let publishRelay = PublishRelay<Int>()
              let subscribe = publishRelay.subscribe{ (next) in
                  print("subscribe: ", next.element!)
              }
              publishRelay.accept(1)
              publishRelay.accept(2)
    
      subscribe:  1
      subscribe:  2
    

Subject와 차이

Subject와 2가지 차이점을 빼면 똑같이 동작함

  • complete 없음
  • error emit 안 함
  • 즉 이벤트 보내기만 하고, 종료도 안 됨
  • Dispose 전까지 계속 작동하므로 UI Event에서 사용

BehaviorRelay

  • .value로 현재 값 꺼낼 수 있음

              let behaviorRelay = BehaviorRelay(value: 0)
              behaviorRelay.accept(1)
              let subscribe = behaviorRelay.subscribe{ (next) in
                  print("subscribe: ", next.element!)
              }
              behaviorRelay.accept(2)
              print("value: ", behaviorRelay.value)
    
      subscribe:  1
      subscribe:  2
      value:  2
    




Publish랑 Behavior 릴레이를 많이 써본 것 같다. 초기값이 필요한 textField와 연동할 때는 Behavior, 네트워크 결과 등 무언가에 대한 결과가 있어야 할 때 등은 Publish 처럼


태그: ,

카테고리:

업데이트:

댓글남기기