Sponsor Link
Publisher
Apple のドキュメントは、こちら。
「時間とともに、値の列を送信するタイプ」として説明されています。実際には、protocol です。
Publisher 例(TimerPublisher)
Timer クラスは、以下のように、Timer.TimerPublisher を提供するようになりました。
Timer.TimerPublisher(interval: TimeInterval, tolerance: TimeInterval? = nil, runLoop: RunLoop, mode: RunLoop.Mode, options: RunLoop.SchedulerOptions? = nil)
Timer クラスから直接提供することもできます。
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 のタイプを含めて定義する必要があります。
let mySubject = PassthroughSubject<String, Error>()
mySubject.send("TestValue")
mySubject.send(completion: .failure(....))
上記では、送られてくるデータは、String 型で、エラー時には、Error が送信されてくると定義しています。
定義した後に、PassthroughSubject を経由して、”TestValue” を送っています。
その後、エラーを送っています。
# エラーは、別に定義が必要ですが、省略しています。
send(completion:) は、エラーだけでなく、非エラーケースでのデータ終了(今後データを送ることはない)を通知するためにも使われます。
Publisher の使い方
Publisher に対して、sink することで、Publisher から値が送信された時に 受け取ることができます。
# assign を使うと、受け取った値をプロパティに設定することができますが、sink を使うことができれば同様のことができますので、急いで理解しなくとも良いと思います。
TimerPublisher (エラーを送ってこない Publisher) の使い方
先ほど見たように、TimerPublisher は、エラーを送ってこないので、シンプルに記述することができます。
let cancellable = Timer.publish(every: 3, on: .main, in: .default)
.autoconnect()
.sink { (value) in
print("receive: \(value)")
}
例えば、上記のコードでは、3秒ごとに、受け取った value (Date 型) を print します。
sink したときの返り値 cancellable は、自分で保持しておかないといけません。スコープ外に外れてしまうと 消去されてしまい、Publisher がデータを送付しても受け取れなくなってしまいます。
PassthroughSubject (エラーを送ってくるかもしれない Publisher) の使い方
PassthroughSubject は、エラーを送ってくるかもしれませんので、そこも含めて sink する必要があります。
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 したときの返り値は、保存しておかないと、呼ばれなくなってしまう
Swift 学習におすすめの本
詳解Swift
Swift の学習には、詳解 Swift という書籍が、おすすめです。
著者は、Swift の初期から書籍を出していますし、Swift の前に主力言語だった Objective-C という言語についても同様の書籍を出しています。
最新版を購入するのがおすすめです。
現時点では、上記の Swift 5 に対応した第5版が最新版です。
Swift ポケットリファレンス
Swift を学んでも、プログラミング言語の文法を全て記憶しておくことは無理なので、ちょっとした文法の確認をするために、リファレンス本を手元に置いておくと便利です。
Swift4 までしか対応していないので、相違点を理解して参照する必要があります。
説明は以上です。
不明な点やおかしな点ありましたら、こちらまで。
Sponsor Link