sink(receiveValue:)の戻り値を破棄せずに保持しておく必要がある理由を探す

本記事は下記を参考にしています。

nextpublishing.jp


結論

そういう仕様。

This method creates the subscriber and immediately requests an unlimited number of values, prior to returning the subscriber. The return value should be held, otherwise the stream will be canceled.
https://developer.apple.com/documentation/combine/just/sink(receivevalue:)

もう少し詳しく見る。

開発環境

> xcodebuild -version
Xcode 13.1
Build version 13A1030d

sink(receiveValue:)の戻り値を保持しないと受信処理は無効

https://developer.apple.com/documentation/combine/just/sink(receivevalue:)

戻り値破棄

import Combine

let subject = PassthroughSubject<String, Never>()

final class Receiver {
    init () {
        subject
            .sink { value in
                print("received:", value)
            }
    }
}

let receiver = Receiver()
subject.send("a")  // printされない
subject.send("b")  // printされない

戻り値保持

import Combine

let subject = PassthroughSubject<String, Never>()

final class Receiver {
    let subscription: AnyCancellable

    init () {
        subscription = subject
            .sink { value in
                print("received:", value)
            }
    }
}

let receiver = Receiver()
subject.send("a")  // "received: a"
subject.send("b")  // "received: b"

なぜ戻り値を破棄せずに保持しておく必要があるのか?

純粋な疑問。

sink(receiveValue:)の戻り値

A cancellable instance, which you use when you end assignment of the received value. Deallocation of the result will tear down the subscription stream.
https://developer.apple.com/documentation/combine/just/sink(receivevalue:)

「受信した値の割り当てを終了するときに使用するキャンセル可能なインスタンス。 結果の割り当てを解除すると、サブスクリプションストリームが破棄されます。」

この戻り値(キャンセル可能なインスタンス)を破棄することでなぜsinkのクロージャが実行されないのだろう。

This method creates the subscriber and immediately requests an unlimited number of values, prior to returning the subscriber. The return value should be held, otherwise the stream will be canceled.
https://developer.apple.com/documentation/combine/just/sink(receivevalue:)

「このメソッドは、subscriberを作成し、subscriberを返す前に、無制限の数の値をすぐに要求します。戻り値を保持する必要があります。保持しないと、ストリームがキャンセルされます。」

仕様とのこと。(それはそう)

  • 戻り値を保持する: 無制限の数の値を要求する→その瞬間はsendが行われないが、戻り値を保持するためサブスクリプションストリームは死なない→キャンセル前の任意のタイミングでsendが行われるとsinkのクロージャが実行される
  • 戻り値を保持しない: : 無制限の数の値を要求する→その瞬間はsendが行われないが、戻り値を保持しないためサブスクリプションストリームは死ぬ

今の所上記の理解。(ややこしい)

参考