第2章 SubscribeとSubscription
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 メソッドには戻り値があり、それを保持しないと受信処理が行われない。
ここが頭に入ってこなかった。というのも、そういものだと受け入れればいいことなのかもしれないが、もう少し深く見て理解したい。
↓
sink(receiveValue:)の戻り値を破棄せずに保持しておく必要がある理由を探す - カルボナーラ街道
第3章 Publisher
import Combine let subject = PassthroughSubject<String, Never>() let publisher = subject.eraseToAnyPublisher() final class Receiver { var subscriptions = Set<AnyCancellable>() init() { publisher .sink { value in print("received:", value) } .store(in: &subscriptions) } } let receiver = Receiver() subject.send("a") // "received: a" subject.send("x") // "received: x"
Subjectをどこかに渡す時はeraseToAnyPublisher()を使ってPassthroughSubjectからAnyPublisherに型を変更して、ただのPublisherとして渡す。
そうすることでSubject特有のsendを外部から実行できないようにする。
第4章 Operator
4.1 バインディング
import Combine final class Model { @Published var value: String = "0" } let model = Model() final class ViewModel { var text: String = "" { didSet { print("didSet text:", text) } } } final class Receiver { var subscriptions = Set<AnyCancellable>() let viewModel = ViewModel() init() { model.$value .assign(to: \.text, on: viewModel) .store(in: &subscriptions) } } let receiver = Receiver() model.value = "1" model.value = "2" model.value = "3"
おさらいだが、model.$value に対して .store(in:) を指定する必要がある。
これにより model.$value のサブスクリプションストリームが即時で破棄されない。
第5章 Combineのコンセプト
5.2 リアクティブプログラミングとは
それら(非同期イベント)を扱う仕組みは既に存在しています。FoundationやUIKitでは、Delegate、~
Delegateはたしかに宣言的な記述で非同期イベントの処理を行っている。言われてみれば確かにそうだと思った。
感想
- 過去にCombineを試したことはあっても、中々理解できてなかった。今回で触りの部分は結構理解できた実感があって読んでよかった
- 著者の方も言っていたが、Publisherの説明としてSubjectを用いることでsendを開発者側でハンドリングできるため、理解しやすかった