Subject와 Relay의 개념에 대해 알아 보겠습니다.
지난 블로그Observable편에서 Observable이 무엇이고 어떻게 만드는지에 대해 배웠습니다.
이번장에선 Observable이자 Observer인 Subject의 개념에 대해 알아보도록 하겠습니다.
Subject란
좀 더 나아가 개발을 할때 실시간으로 Observable에 값을 추가하고 Subscriber를 할 수 있는 놈이 필요합니다.
이때 Observable이자 Observer인것을 Subject라고 합니다.
Observable + Observer = Subject라는 이 부분의 의미를 자세히 고민해보세요.
확실히 알고 넘어가야합니다.
이벤트를 외부에 전달해줄 경우에 사용해서, Delegate대신 사용하기도 합니다.
종류
- PublishSubject
- BehaviorSubject
- ReplaySubject
PublishSubject
PublishSubject는 .completed, .error이벤트가 발생할때까지, 즉 종료될때까지 subscribe한 이후부터 이벤트를 방출 합니다.
let subject = PublishSubject<Int>()
let subjectOne = subject
.subscribe(onNext: { (num) in
print("subjectOne :",num)
})
subject.onNext(1)
subject.onNext(2)
let subjectTwo = subject
.subscribe(onNext: { (num) in
print("subjectTwo :", num)
})
subject.onNext(3)
subject.onNext(4)
subject.onNext(5)
/*
subjectOne : 1
subjectOne : 2
subjectOne : 3
subjectTwo : 3
subjectOne : 4
subjectTwo : 4
subjectOne : 5
subjectTwo : 5
*/
subject가 완전종료된 후 새로운 subscriber가 생긴다고 다시 subject가 작동하진 않습니다.
또 subject가 종료되었을 때에 Subscriber에게 종료 이벤트를 줄 뿐만 아니라, 이 후에 구독한 subscriber에게도 종료이벤트를 알려 줍니다!
let subject = PublishSubject<Int>()
let subjectOne = subject
.subscribe(onNext: { (num) in
print("subjectOne :",num)
}, onError: { (error) in
print("subjectOne Erorr: ",error)
}, onCompleted: {
print("subjectOne onCompleted")
})
subject.onNext(1)
subject.onNext(2)
subject.onCompleted() // 추가
let subjectTwo = subject
.subscribe(onNext: { (num) in
print("subjectTwo :",num)
}, onError: { (error) in
print("subjectTwo Erorr: ",error)
}, onCompleted: {
print("subjectTwo onCompleted")
})
subject.onNext(3)
subject.onNext(4)
subject.onNext(5)
/*
subjectOne : 1
subjectOne : 2
subjectOne onCompleted
subjectTwo onCompleted
*/
BehaviorSubject
BehaviorSubject는 PublicshSubject와 유사하지만, 초기값을 가집니다.
PublishSubject와 달리 항상 직전의 값부터 구독합니다!
초기값이 없다면 PublishSubject를 사용하세요!
위의 마블을 보시면 PublishSubject와 달리 항상 직전의 값부터 구독하시는걸 볼 수 있습니다.
let subject = BehaviorSubject(value: 5)
let subjectOne = subject
.subscribe(onNext: { (num) in
print("subjectOne :",num)
}, onError: { (error) in
print("subjectOne Erorr: ",error)
}, onCompleted: {
print("subjectOne onCompleted")
})
subject.onNext(6)
subject.onNext(7)
subject.onNext(8)
let subjectTwo = subject
.subscribe(onNext: { (num) in
print("subjectTwo :",num)
}, onError: { (error) in
print("subjectTwo Erorr: ",error)
}, onCompleted: {
print("subjectTwo onCompleted")
})
subject.onNext(9)
subject.onNext(10)
/*
subjectOne : 5
subjectOne : 6
subjectOne : 7
subjectOne : 8
subjectTwo : 8
subjectOne : 9
subjectTwo : 9
subjectOne : 10
subjectTwo : 10
*/
ReplaySubject
ReplaySubject는 생성시 선택한 특정 크기만큼 일시적으로 캐시하거나 버퍼를 저장해서 최신 요소를 모두 방출합니다.
최근 검색어 같은 곳에 사용하면 좋을꺼같아요.
let subject = ReplaySubject<Int>.create(bufferSize: 3)
subject.onNext(1)
subject.onNext(2)
subject.onNext(3)
subject.onNext(4)
subject.onNext(5)
subject.onNext(6)
let subjectOne = subject.subscribe(onNext: { (num) in
print(num)
})
subject.onNext(7)
subject.onNext(8)
subject.onNext(9)
/*
4
5
6
7
8
9
*/
Relay란
Relay Class는 RxCocoa4에서 구현되었고, PublishRelay와 BehaviorRelay클래스가 존재합니다.
RxSwift인 Subject와는 다르게 Relay는 RxCocoa의 클래스 입니다.
PublishRelay
PublishRelay는 PublishSubject의 Wrapper 클래스입니다.
PublishSubject의 특성처럼 구독 이후의 발생하는 이벤트들만 알 수 있습니다.
public final class PublishRelay<Element>: ObservableType {
private let _subject: PublishSubject<Element>
public init() {
_subject = PublishSubject()
}
}
BehaviorRelay
BehaviorRelay는 BehaviorSubject의 Wrapper 클래스 입니다.
.value를 통해서 현재의 값을 가져올 수 있습니다.
variable이 Deprecate되면서 소개시켜드리지 않았지만 대신에 BehaviorRelay를 사용하시면 됩니다.
public final class BehaviorRelay<Element>: ObservableType {
private let _subject: BehaviorSubject<Element>
public var value: Element {
return try! _subject.value()
}
public init(value: Element) {
_subject = BehaviorSubject(value: value)
}
}
~Subject와 ~Relay의 차이점
~Subject는 .completed, .error의 이벤트가 발생하면 subscribe가 종료되는 반면,
~Relay는 .completed, .error를 발생하지 않고 Dispose되기 전까지 계속 작동하기 때문에 UI Event에서 사용하기 적절합니다.
'RxSwift' 카테고리의 다른 글
[RxSwift] filter vs skip operator (0) | 2019.09.14 |
---|---|
[RxSwift] Observable이란 - (2) (0) | 2019.07.25 |
[RxSwift] RxSwift의 기본 개념 - (1) (0) | 2019.07.25 |