combine (1) - Publisher, Subscriber
Publisher Protocol
public protocol Publisher<Output, Failure> {
associatedtype Output
associatedtype Failure : Error
}
✔️ 말 그대로 Publish(발행)하는 프로토콜. Subscriber의 instance에게 elements를 전달.
✔️ Publisher의 associated types인 Output, Failure는 -> Subscriber의 associated types인 Input, Failure과 매치됨
✔️ Publisher는 subscriber를 받아들이기 위해 receive(subscriber:)를 함(Publisher와 Subscriber가 연결되는 행위).
✔️ 그래야 Publisher가 발행 하는 값을 Subscriber가 받을 수 있음.
이후, publisher는 subscriber가 가진 아래 3가지 메서드를 호출할 수 있음.
2. 나만의 Publisher 만들기도 가능 (아직은 무슨 말인지 모르겠음)
✔️ send(_:) 메서드를 호출하여 필요에 따라 값을 게시하려면 PassthroughSubject와 같은 제목의 구체적인 서브 클래스를 사용
✔️ 값을 업데이트할 때마다 publish 하기 위해 CurrentValueSubject 사용
✔️ 프로퍼티 앞에 @Published 키워드를 붙이면, 그 프로퍼티의 값이 변할 때마다 이벤트를 방출하는 publisher를 얻을 수 있음
Subcriber Protocol
✔️ Publisher가 방출한 값(a stream of elements)을 받는 주체
✔️ Subscriber의 Input, Failure는 Publisher의 Output, Failure와 매칭되어야 함
✔️ Publisher과 연결되기 위해서는 해당 publisher의 subscribe(_:) 메서르를 호출해야 함
public func subscribe<S>(_ subscriber: S) where S : Subscriber, Self.Failure == S.Failure, Self.Output == S.Input
✔️ 이 메서드를 호출하면 publisher는 subscriber의 1️⃣ receive(subscription:)를 실행시키는데, 이 때 subscription을 받게 됨. (subscription이 있어야 원하는 요구를 publisher한테 할 수 있게 됨)
✔️ subscriber가 첫 번째 요구(demand)를 한 후에 publisher는 2️⃣receive(_:)를 호출
✔️ 그리고 발행이 끝나면, 3️⃣receive(completion:)를 호출
public protocol Subscriber<Input, Failure> : CustomCombineIdentifierConvertible {
associatedtype Input
associatedtype Failure : Error
func receive(subscription: Subscription)
func receive(_ input: Self.Input) -> Subscribers.Demand
func receive(completion: Subscribers.Completion<Self.Failure>)
}
Subcribers.Demand
구독권(subscription)을 통해 구독자(subscriber)가 발행자(publisher)에게 요청한 항목의 수.
Subcribers.Completion
publisher가 더 이상 elements를 생성하지 않겠다는 뜻!
왜냐? 발행이 정상적으로 완료되었거나 error로 끝났기 때문에
예시
string값을 받는 subscriber 만들기 (Subscriber 프로토콜 채택)
class StringSubscriber: Subscriber {
typealias Input = String
typealias Failure = Never
func receive(subscription: Subscription) {
print("Received Subscription")
}
func receive(_ input: String) -> Subscribers.Demand {
print("Recived Value: ", input)
return .none
}
func receive(completion: Subscribers.Completion<MyError>) {
print("Completed")
}
}
subscriber가 구독(subcribe) 시작
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let publisher = ["1", "2", "3", "4", "5"].publisher
let subscriber = StringSubscriber() // 나는 구독자
publisher.subscribe(subscriber)
}
}
subscriber 이놈이 나를 구독했구만? 그러면 구독권(Subcription)을 줄게!
-> receive(subscription:) 메서드가 호출되며, subcription을 받음.
그런데, 이렇게만 하고 print문을 찍어보면 아래와 같이 Subscription을 받은 것만 나옴
Received Subscription
🤦🏻♀️ 왜 주는데 받지를 못하니?
얻고 싶은 게 있다면, 받은 subscription을 가지고 원하는 것을 요청(request)해야 함.
func receive(subscription: Subscription) {
print("Received Subscription")
subscription.request(.max(1)) // backpressure - 1개의 결과만 받겠다! 네가 가진 게 100개라도 난 3개만 필요해
}
이렇게만 하고 print문을 찍어보면 아래와 같이 Recived Value가 1만 출력됨
Received Subscription
Recived Value: 1
.unlimited로 설정하니 모든 값을 다 받을 수 있었음!
Completed는 아래처럼 1️⃣모든 값을 다 받았을 때 (여기서는 ["1", "2", "3", "4", "5"])
2️⃣error의 결과일 때 불려짐.
class StringSubscriber: Subscriber {
typealias Input = String
typealias Failure = Never
func receive(subscription: Subscription) {
print("Received Subscription")
subscription.request(.unlimited)
}
func receive(_ input: String) -> Subscribers.Demand {
print("Recived Value: ", input)
return .none
}
func receive(completion: Subscribers.Completion<Never>) {
print("Completed")
}
}
또한 receive(subscription:)에서 max(1)값을 요구했더라도,
receive(:)에서 요구를 수정할 수 있음.
class StringSubscriber: Subscriber {
typealias Input = String
typealias Failure = Never
func receive(subscription: Subscription) {
print("Received Subscription")
subscription.request(.max(1)) // backpressure - 3개의 결과만 받겠다! 네가 가진 게 100개라도 난 3개만 필요해
}
func receive(_ input: String) -> Subscribers.Demand {
print("Recived Value: ", input)
return .max(1)
}
func receive(completion: Subscribers.Completion<Never>) {
print("Completed")
}
}
출력되는 결과
Received Subscription
Recived Value: 1
Recived Value: 2
Recived Value: 3
Recived Value: 4
Recived Value: 5
Completed
출처
-https://developer.apple.com/documentation/combine/subscriber
Apple Developer Documentation
developer.apple.com
- https://nsios.tistory.com/181
[Swift] Combine의기본 Publisher이란?
예전에 Published를 스유를 기준으로 다뤘다면 이번에는 비동기를 기준으로 다룰 Publisher에 대해 알아보려고해요 둘이 다른건 아니에요! 스위프트 API에서 이미 많은 publisher를 지원하고있어요 이렇
nsios.tistory.com
https://zeddios.tistory.com/966
Combine (1-1) - Subcribers.Demand
안녕하세요 :) Zedd입니다. https://zeddios.tistory.com/925 Combine (1) - Publisher, Subscriber 안녕하세요 :) Zedd입니다. 이번 휴가동안 SwiftUI를 좀 해볼라하는데 Combine모르면 이거 걍 노답임.... -> 휴가 끝나버렸
zeddios.tistory.com