Sponsor Link
目次
Publisher
Apple のドキュメントは、こちら。
「時間とともに、値の列を送信するタイプ」として説明されています。実際には、protocol です。
Publisher 例(TimerPublisher)
Timer クラスは、以下のように、Timer.TimerPublisher を提供するようになりました。
1 2 3 |
Timer.TimerPublisher(interval: TimeInterval, tolerance: TimeInterval? = nil, runLoop: RunLoop, mode: RunLoop.Mode, options: RunLoop.SchedulerOptions? = nil) |
Timer クラスから直接提供することもできます。
1 2 3 |
Timer.publish(every interval: TimeInterval, tolerance: TimeInterval? = nil, on runLoop: RunLoop, in mode: RunLoop.Mode, options: RunLoop.SchedulerOptions? = nil) -> Timer.TimerPublisher |
どちらも 返り値として TimerPublisher を返します。
引数を見て想像できるように、この Publisher は、指定した時間経過毎に、値を送信してきます。
TimerPublisher の詳細を確認すると、以下のようになっています。
- 送信してくる値のタイプとして、Timer.TimerPublisher.Output に Date が typealias されています。
- Timer.TimerPublisher.Failure に Never と設定されていることから この Publisher は、エラーを送ることはないとわかります。
Publisher 例(PassthroughSubject)
エラーを送ってくるかもしれない Publisher の1つとして、PassthroughSubject という Publisher があります。
PassthroughSubject は、外部から、値を送ることをリクエストすることができる Publisher (の1つ)です。
Send メソッドを使うことで、PassthroughSubject に値を送るようにリクエストできます。
PassthroughSubject を定義する時には、Output のタイプを含めて定義する必要があります。
1 2 3 4 5 |
let mySubject = PassthroughSubject<String, Error>() mySubject.send("TestValue") mySubject.send(completion: .failure(....)) |
定義した後に、PassthroughSubject を経由して、”TestValue” を送っています。
その後、エラーを送っています。
# エラーは、別に定義が必要ですが、省略しています。
Publisher の使い方
Publisher に対して、sink することで、Publisher から値が送信された時に 受け取ることができます。
# assign を使うと、受け取った値をプロパティに設定することができますが、sink を使うことができれば同様のことができますので、急いで理解しなくとも良いと思います。
TimerPublisher (エラーを送ってこない Publisher) の使い方
先ほど見たように、TimerPublisher は、エラーを送ってこないので、シンプルに記述することができます。
1 2 3 4 5 6 7 |
let cancellable = Timer.publish(every: 3, on: .main, in: .default) .autoconnect() .sink { (value) in print("receive: \(value)") } |
例えば、上記のコードでは、3秒ごとに、受け取った value (Date 型) を print します。
PassthroughSubject (エラーを送ってくるかもしれない Publisher) の使い方
PassthroughSubject は、エラーを送ってくるかもしれませんので、そこも含めて sink する必要があります。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 |
enum MyError: String, Error { case IntentionalError = "IntentionalError" } let myPS = PassthroughSubject<String, MyError>() let cancellable = myPS.sink(receiveCompletion: { (completion) in switch completion { case .finished: print("finished successfully") case .failure(let error): print("error occured: \(error)") }}, receiveValue: { (value) in print("value received: \(value)") }) myPS.send("test") --> value received: test //myPS.send(completion: .finished) // --> finished successfully myPS.send(completion: .failure(.IntentionalError)) --> error occured: IntentionalError |
まとめ:Publisher を理解するポイント
- Publisher は、時間と共にデータを送ってくる
- .sink することで、データが送られてきた時に処理することができる
- Publisher には、データを確実に送ってくる Publisher と Failure を送ってくるかもしれない Publisher がある
- .sink したときの返り値は、保存しておかないと、呼ばれなくなってしまう
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link