Subject
A publisher that exposes a method for outside callers to publish elements.
외부 호출자가 요소를 게시할 수 있도록 메서드를 노출하는 게시자입니다.
Subject
또한 프로토콜이다. Subject
도 쉽게 생각하면, publisher
의 한 종류이다.
protocol Subject : AnyObject, Publisher
왜냐하면, Subject
또한 publisher
를 채택받고 있기 때문이다.
자그럼 둘은 무슨 차이냐!
일반 publisher
같은 경우 선언과 동시에 방출될 값이 정해진다.
예를 들어, Just
같은 경우에도
let justPublisher = Just("Combine 첫 교시")
정해진 "Combine 첫 교시"
라는 값 밖에 방출하지 못한다.
다른 여타 publisher
도 형태만 다를 뿐이지 선언과 동시에 정해진 값 밖에 방출하지 못하는 것은 같다.
또한 값을 모두 방출하면, 자동적으로 completion
이 호출된다.
하지만, Subject
같은 경우 추가적인 요소를 방출할 수 있다.
자세한 사용법은 코드로 확인하고, 그전에 구현되어 있는 Subject
소개하자면, 두개가 존재한다.
- CurrentValueSubject
- PassthroughSubject
둘의 차이는 "초기값이 있냐, 없냐"의 차이이다.
CurrentValueSubject
CurrentValueSubject
이녀석은 초기값이 있는 Subject
var subscriberBag = Set<AnyCancellable>()
let currentValueSubject = CurrentValueSubject<String, Never>("Safari")
currentValueSubject.sink { completion in
print(completion)
} receiveValue: { value in
print(value)
}.store(in: &subscriberBag)
Safari
위와 같이 CurrentValueSubject
는 생성자에 초기값을 넣어줘야 한다.
실행해보면, Safari
호출되고 completion
이 호출되지 않는 것을 볼 수 있다.
이는 아직 CurrentValueSubject
의 작업이 끝나지 않았음을 알 수 있다.
currentValueSubject.value = "Combine"
currentValueSubject.send("swift")
위 코드를 아래에 추가하면,
Combine
swift
위와 같이 값을 추가로 방출하는 것을 볼 수 있다.
이번엔,
currentValueSubject.send(completion: .finished)
currentValueSubject.send("Rxswift")
위 같이 코드를 추가하면,
finished
finished
가 호출되고 더이상 "Rxswift"
라는 값은 방출하지 않는다.
이는 completion
를 통해 작업이 끝났음을 선언했기 때문이다.
위와 같이 Subject
같은 경우 send
메서드를 통해 추가적인 값 방출이 가능하다
전체 코드,
var subscriberBag = Set<AnyCancellable>()
let currentValueSubject = CurrentValueSubject<String, Never>("Safari")// 필수적으로 초기값이 필요
currentValueSubject.sink { completion in
print(completion)
} receiveValue: { value in
print(value)
}.store(in: &subscriberBag)
currentValueSubject.value = "Combine"
currentValueSubject.send("swift")
currentValueSubject.send(completion: .finished)
currentValueSubject.send("Rxswift")
Safari
Combine
swift
finished
PassthroughSubject
PassthroughSubject
같은 경우 currentValueSubject
보다 심플하다.
따로 초기값이 없기 때문이다.
enum InputError: Error {
case unkown
}
let passthroughSubject = PassthroughSubject<String, InputError>()
passthroughSubject.sink { result in
switch result {
case .finished:
print("input 끝")
case .failure(let error):
print(error.localizedDescription)
}
} receiveValue: { value in
print(value)
}.store(in: &subscriberBag)
위와 같이 생성자에 초기값이 들어가지 않는다.
passthroughSubject.send("m1Mac")
passthroughSubject.send("사고싶다.")
때문에 위와 같이 send
메서드를 통해 보낸 값만을 방출한다.
m1Mac
사고싶다.
또한, send(completion:)
메서드는 .finished
만 보내는것이 아닌 Subject
가 Error를 방출한다면,
passthroughSubject.send(completion: .failure(.unkown))
passthroughSubject.send("더이상 input를 받지 않음")
.failure
를 통해 Error 방출이 가능하다.
unkown
역시 completion
이 호출되었기 때문에 아래의 "더이상 input를 받지 않음"
이라는 값을 방출하지 않는다.
전체 코드,
var subscriberBag = Set<AnyCancellable>()
enum InputError: Error {
case unkown
}
let passthroughSubject = PassthroughSubject<String, InputError>()
passthroughSubject.sink { result in
switch result {
case .finished:
print("input 끝")
case .failure(let error):
print(error)
}
} receiveValue: { value in
print(value)
}.store(in: &subscriberBag)
passthroughSubject.send("m1Mac")
passthroughSubject.send("사고싶다.")
passthroughSubject.send(completion: .failure(.unkown))
//passthroughSubject.send(completion: .finished)
passthroughSubject.send("더이상 input를 받지 않음")
m1Mac
사고싶다.
unkown
'Swift' 카테고리의 다른 글
[Swift] Alamofire의 RequestInterceptor을 사용해 토큰 갱신하기 (0) | 2024.01.18 |
---|---|
Combine 뽀개기 4장: Scheduler (0) | 2023.07.26 |
Combine 뽀개기 2장: Subscriber (0) | 2023.07.26 |
Combine 뽀개기 1장: Publisher (0) | 2023.07.26 |
[Swift] Swift Concurrency와 GCD (1) | 2022.12.14 |