본문 바로가기

iOS/학습정리

iOS) RxSwift 가볍게 훑어보기 (2) PublishSubject

PublishSubject

Observer이면서 Observable

Subject로 전달되는 이벤트를 Observer로 전달하는 가장 기본적인 Subject이다. 즉 이벤트를 전달하는 역할과 이벤트를 전달받는 역할 모두를 할 수 있다.

코드로 알아보자

let dispose Bag = DisposeBag()

enum MyError: Error {
    case error
}

기본적인 세팅은 다음과 같이 할 수 있다.

let subject = PublishSubject<String>()

위 코드에서 subject는 문자열이 포함된 next event를 받아서 다른 observer에게 전달할 수 있다. 생성자를 호출할 때에는 파라미터를 전달하지 않는다. subject는 비어있는 상태로 생성되는 것으로, 생성 시점에는 내부에 아무 이벤트도 저장되어 있지 않다. 생성 직후에 observer가 구독을 시작하면 아무런 이벤트도 전달되지 않는다.

subject.onNext("Hello")

위 코드를 실행하면 subject로 next event가 전달된다. 지금은 subject를 구독하는 observer가 없기 때문에 해당 이벤트는 처리되지 않고 사라진다.

이벤트가 사라지는게 문제가 된다면 ReplaySubjectCold Observable을 사용해야 한다.

let o1 = subject.subscribe { print(">> 1", $0) }
o1.disposed(by: disposeBag)

이 코드만으로는 콘솔에 아무것도 출력되지 않는다. PublishSubject는 구독 이후에 생긴 새로운 이벤트만 구독자에게 전달한다. 따라서 o1이 구독하기 전에 생성되었던 "Hello"를 담은 이벤트는 전달되지 않는다.

subject.onNext("RxSwift")

"RxSwift"를 담은 이벤트가 subject로 전달되고 subject는 이 이벤트를 o1에게 전달한다. 결과를 보면 다음과 같다.

>> 1 next(RxSwift)

전체 코드가 다음과 같을 때에 결과는 어떻게 될까?

let dispose Bag = DisposeBag()

enum MyError: Error {
    case error
}

let subject = PublishSubject<String>()
subject.onNext("Hello")

let o1 = subject.subscribe { print(">> 1", $0) }
o1.disposed(by: disposeBag)

subject.onNext("RxSwift")

let o2 = subject.subscribe { print(">>2", $0) }
o2.disposed(by: disposeBag)

subject.onNext("Subject")

subject.onCompleted()

let o3 = subject.subscribe { print(">>3", $0) }
o2.disposed(by: disposeBag)
>> 1 next(RxSwift)
>> 1 next(Subject)
>> 2 next(Subject)
>> 1 completed
>> 2 completed
>> 3 completed

Completed 이벤트 이후에 구독한 observer는 바로 Completed Event를 받는다.

// subject.onCompleted()
subject.onError()

Completed event 대신 Error event를 전달하면 o1, o2, o3 모두 에러 이벤트를 전달 받는다.

>> 1 next(RxSwift)
>> 1 next(Subject)
>> 2 next(Subject)
>> 1 error(error)
>> 2 error(error)
>> 3 error(error)

참고