INEEDACHACHA

Combine - Subscriber (컴바인 구독) 본문

iOS

Combine - Subscriber (컴바인 구독)

INEEDACHACHA 2024. 3. 20. 17:28

개념

  • Publisher에서 나오는 요소의 흐름을 받는다.

Flow

  • Publisher<Int, Never>는 Publisher의 Output과 Failure 타입을 나타낸다.
  • Publisher에 Output과 Failure가 있듯이, Subscrier에는 Input과 Failure가 있다.

Publisher

  • Output: publisher가 방출하는 값의 종류
  • Failure: publisher가 방출할 수 있는 에러의 종류

Subscriber

  • Input: subscriber가 받는 값의 종류
  • Failure: subscriber가 받을 수 있는 에러의 종류

따라서 Subscriber의 <Input, Failure>의 associated type은 publisher의 <Output, Failure> 타입과 일치해야한다.

Proctocol

  • Subscriber protocol에는 Input, Failure 외에도 3개의 메소드가 정의되어 있다.

receive(subscription:)

  • subscriber와 publisher를 연결하기 위해 subscribe( :)함수를 부르고 난 뒤에 publisher가 호출하는 함수
  • 이 함수는 subscriber에게 subscription 인스턴스를 전달해준다.
    subscription.cancle() 
  • 상기와 같이 subscription 명시적으로 취소하지 않으면 publisher가 완료될 때 까지 또는 일반적인 메모리 관리로 인해 저장된 subscription이 초기화 되지 않을 때 까지 계속 유진된다.

receive(_:)

  • subscriber의 첫 번째 요청(initial demand)이 이뤄지고 나면 publisher가 새롭게 발행된 element 들을 subscriber로 전달하기 위해 호출하는 함수.
  • 이 때 subscriber의 첫 번째 요청이란 subscriber가 Subscription protocol에 정의된 request를 호출하는 행위를 뜻한다.

receive(completion:)

  • subscriber에게 publishing이 정상적으로 끝났는지 또는 에러로 인해 끝났음을 알려주는 함수이다
  • 파라미터 타입은 Subscribers.Completion이다.

Subscriber

  • Subscriber를 상속해서 위와 같은 함수들을 직접 구현할 수도 있지만, 애플에서는 그런 방법들을 권장하지 않는다.
  • Combine은 Publisher 타입의 Operator를 통해 하기와 같은 Subscriber를 제공한다.

sink(receiveCompletion: receiveValue:)

  • 종료 시그널을 받거나 매번 새로운 요소를 받았을 때 임의적인 closure를 실행한다.

assign(to:on:)

  • 매번 새로 받은 값을 주어진 인스턴스의 key path로 정의되는 property에 할당한다.

흐름도

직접 구현


// 1부터 6까지의 값을 방출하는 Publisher를 생성한다.
let publisher = (1...6).publisher

// Subscriber를 상속받는 custom subscriber를 만든다.
final class IntSubscriber: Subscriber {

    // type alias를 통해 Output과 Failure 타입과 일치하는 Input, Failure 타입을 각각 정의한다.
    typealias Input = Int
    typealias Failure = Never

    // publisher에서 생성된 구독권을 (subscription)을 받을 때 쓰임
    func receive(subscription: Subscription) {
        subscription.request(.max(3))
    }

    // 각 값을 수신할 때 호출되는 함수
    func receive(_ input: Int) -> Subscribers.Demand {
        print("Received value", input)
        // .none을 반환하는 것의 의미는 subscriber의 수요 변화가 없을을 나타낸다.
        // 즉 .max(0)와 같은 의미이다.
        return .none
    }

    func receive(_ input: Int) -> Subscribers.Demand {
        print("Received value", input)
        // publisher가 생산할 수 있는대로 받겠다는 의미.
        return .unlimited
    }

    // 완료 이벤트를 받을 때 호출되는 함수
    func receive(completion: Subscribers.Completion<Never>) {
        print("Received completion", completion)
    }

}

// Subscriber 생성
let subscriber = IntSubscriber()
// Publisher에게 구독자를 붙임
publisher.subscribe(subscriber)