저번에 살펴보았던 Publisher와 Subscriber에 이어서 Subject에 대해 살펴보도록 하겠다.
회사에서 개발된 코드의 VM에는 CurrentValueSubject, PassthroughSubject가 즐비하게 늘어서 있기 때문에 무적권 알아둬야 할 것 같다..
Subject란?
subject는 외부 발신자가 element를 publish할 수 있는 방법을 제공하는 publisher이다.
그냥 publisher라고 이해해보자..
이러한 Subject는 Publisher 프로토콜을 채택하고 있다.
Combine에는 미리 만들어진 Subject가 2가지 존재한다.
1. CurrentValueSubject
2. PassThroughSubject
CurrentValueSubject란?
single value를 래핑하고 값이 변경될 때마다 새로운 element를 publish하는 subject이다.
CurrentValueSubject는 가장 최근에 publish 된 element의 버퍼를 유지한다.
CurrentValueSubject에서 send를 호출하면, 현재 값도 업데이트가 된다. -> 값을 직접 업데이트 하는 것과 동일
CurrentValueSubject 예제:
let currentValueSubject = CurrentValueSubject<String, Never>("jun")
let subscriber = currentValueSubject.sink(receiveValue: {
print($0)
})
currentValueSubject.value = "값 변경1"
currentValueSubject.send("값 변경2")
//출력값:
//"jun"
//"값 변경1"
//"값 변경2"
PassthroughSubject란?
downstream subscribers에게 element를 broadcases 하는 subject이다.
CurrentValueSubject와 달리, PassthroughSubject에는 가장 최근에 publish된 element의 초기값 또는 버퍼가 없다.
PassthroughSubject는 Subscriber가 없거나 현재 demand가 0이면 value를 삭제한다. -> 이말 뭔말인지 보충
PassthroughSubject 예제:
let passthroughSubject = PassthroughSubject<String, Never>()
let subscriber = passthroughSubject.sink(receiveValue: {
print($0)
})
passthroughSubject.send("값 변경1")
passthroughSubject.send("값 변경2")
//출력값:
//"값 변경1"
//"값 변경2"
passthroughSubject는 CurrentValueSubject와 달리 생성시 별다른 초기값을 주지 않아도 된다.
Subject는 send() 라는 메소드를 통해 값을 스트림에 "주입"할 수 있는 Publisher이다.
이러한 send() 메소드는 총 3가지가 존재한다.
1. send(completion: Subsrcribers.Completion<Never>)
2. send(input: String)
3. send(subscription: Subscription)
send(completion: Subsrcribers.Completion) 예제
enum MyError: Error {
case unknown
}
let passthroughSubject = PassthroughSubject<String, Error>()
let subscriber = passthroughSubject.sink(receiveCompletion: { (result) in
switch result {
case .finished:
print("finished")
case .failure(let error):
print(error.localizedDescription)
}
}, receiveValue: { (value) in
print(value)
})
passthroughSubject.send("값 변경1")
passthroughSubject.send("값 변경2")
//passthroughSubject.send(completion: .failure(MyError.unknown))
passthroughSubject.send(completion: .finished)
passthroughSubject.send("끝나서 출력 안됨")
출력 결과:
"값 변경1"
"값 변경2"
"finished"
completion을 통해 값을 전달하게 될 경우 그 뒤에 send를 통해 보내지는 모든 값들은 무시 된다.
// Never인 경우 error가 발생할 일이 없다 라는 뜻 -> .failure를 호출할 일이 없음
let passthroughSubject = PassthroughSubject<String, Never>()
// Error인 경우 error가 발생할 수 있다 라는 뜻 -> .failure 호출할 수 있음
let passthroughSubject = PassthroughSubject<String, Error>()
참고링크:
'iOS 개발 > Combine' 카테고리의 다른 글
[Combine] Operater란? (1) (1) | 2023.05.25 |
---|---|
[Combine] Publisher Future와 CompletionHandler의 차이 (0) | 2023.05.24 |
[Combine] CurrentValueSubject & PassthroughSubject 예제(2 - 1) (0) | 2023.05.18 |
[Combine] Publisher & Subscriber란?(1) (0) | 2023.05.16 |
[Combine] Combine 정의(0) (0) | 2023.03.02 |