RxSwift - Relay

JSLee·2022년 3월 21일
0

Relay Class는 RxCocoa4에서 구현되었고, PublishRelay와 BehaviorRelay클래스가 존재합니다.
RxSwift인 Subject와는 다르게 Relay는 RxCocoa의 클래스 입니다.

  • error , completed Event 가 존재하지 않아 생명주기 종료가 없습니다.

  • Dispose 말곤 종료가 없기 때문에 UI 에 접목시키기 좋습니다.

  • Event 의 종류는 accept 만 존재하고 .next 로 방출합니다.

PublishRelay

PublishSubject 와 비슷한 기능을 수행합니다.

(PublishSubject 의 경우 구독전 방출된 Event 를 무시합니다.)

다른 점은 accept 를 통한 Event 방출입니다.

        let pRelay = PublishRelay<Int>()
        
        pRelay.accept(Int.random(in: 0..<4)) //무시
        
        pRelay.subscribe(onNext : {
            print($0)
        }).disposed(by: disposeBag)
        
        pRelay.accept(Int.random(in: 0..<4))
        
        pRelay.subscribe(onNext: {
            print($0)
        }).disposed(by: disposeBag)
        
        pRelay.accept(Int.random(in: 0..<4))

3
1
1

값을 공유 할수 있는 부분도 같습니다.

BehaviorRelay

BehaviorSubject를 wrapping 해서 가지고 있는 객체로서 .value를 사용해 현재의 값을 꺼낼 수 있습니다.(읽기 전용) value를 변경하기 위해서 .accept()를 사용합니다

subject 와의 차이점

  let b = BehaviorSubject<[String]>(value: ["하나","둘","셋","넷"])

        let bValue = b.value

        b.asObservable().subscribe { print($0) }.disposed(by: disposeBag)

        do {
            try b.onNext(bValue() + ["다섯"])
        }catch {
            print(error)
        }

next(["하나", "둘", "셋", "넷"])
next(["하나", "둘", "셋", "넷", "다섯"])

value 에 접근하여 추가 하기 위해선 Subject 는 error를 방출하기 때문에 do catch 문을 사용해주어야 합니다.

 let a = BehaviorRelay<[Int]>(value: [1,2,3,4])
        let v = a.asObservable()
        
        v.subscribe { print($0) }.disposed(by: disposeBag)
        
        a.accept(a.value + [5] )
        

next([1, 2, 3, 4])
next([1, 2, 3, 4, 5])

하지만 Relay 는 error , completed 가 없기때문에 do catch 문이 필요하지 않습니다.

value + 와 accept 의 차이

 a.accept(a.value + [5] )
        
 a.accept([6])

next([1, 2, 3, 4])
next([1, 2, 3, 4, 5])
next([6])

ReplayRelay

RxSwift 6 에서 ReplayRelay 가 추가되었습니다.

ReplaySubject 와 동일 생성 동일 기능을 수행합니다.

하지만 onNext 와 accept 의 차이 그리고

error , completed 의 차이는 존재합니다.

        let r = ReplayRelay<Int>.create(bufferSize: 2)
        (1...10).forEach { r.accept($0) }
        
        r
            .asObservable()
            .subscribe { print($0)}.disposed(by: disposeBag)
        
        let first = r.subscribe { print("첫번째 observer == \($0)")}
        first.disposed(by: disposeBag)
        
        
        let second = r.subscribe { print("두번째 observer == \($0)")}
        second.disposed(by: disposeBag)
        
        r.accept(99)
        r.accept(999)
        r.accept(9999)
next(9)
next(10)
첫번째 observer == next(9)
첫번째 observer == next(10)
두번째 observer == next(9)
두번째 observer == next(10)
next(99)
첫번째 observer == next(99)
두번째 observer == next(99)
next(999)
첫번째 observer == next(999)
두번째 observer == next(999)
next(9999)
첫번째 observer == next(9999)
두번째 observer == next(9999)

🍙 Binder가 RxCocoa에서 RxSwift로 이동(RxSwift 6 릴리스 )

Binder는 이름 그대로 input이나 output을 Binding하기 위해 사용하는데요. 그동안에는 Binder를 사용하기 위해 RxCocoa 모듈을 import 해야만 했습니다.

커뮤니티의 많은 요청에 따라 RxCocoa 모듈에 있던 Binder를 RxSwift로 이동했습니다. RxSwift 6부터는 더 이상 Binder를 사용하기 위해 RxCocoa 모듈을 import할 필요가 없습니다.

Drive , Bind

drive 는 View 의 전환 이나 Alert 등 단순 UI 적 변화에 대응에 사용하면 좋을것 같습니다.

profile
iOS/Android/FE/BE

0개의 댓글