【Swift/Combine】Futureの使い方!コールバックの解消
この記事からわかること
- SwiftのCombineフレームワークの使い方
- Futureの使い所と役割
- 実装サンプル
- Deferredを使用するメリット
index
[open]
\ アプリをリリースしました /
友達や家族の誕生日をメモ!通知も届く-みんなの誕生日-
posted withアプリーチ
SwiftのCombineフレームワークとは非同期処理やストリーム処理、データのバインディング、イベントハンドリングなどのリアクティブプログラミングに倣った機能を提供しているApple純正のフレームワークです。
Futureとは?
final class Future<Output, Failure> where Failure : Error
CombineのFutureは成功(何かしらの値)か失敗を返すシンプルなパブリッシャーです。Combineの強みの1つである「コールバック地獄からの解放」を例にFutureの使い方を見ていきます。
使い方
Futureを返す関数を定義して実際に使用してみます。非同期処理ということでDispatchQueue
で擬似的に再現しています。成功時にはString
型を失敗時にはNever
型を指定します。失敗時には独自のエラー型を指定することも可能です。
おすすめ記事:【Swift】DispatchQueueの使い方!GCDで非同期と遅延処理
func getPublisher() -> Future<String, Never> {
return Future() { promise in
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
promise(.success("成功したよ"))
}
}
}
定義した関数を実装して取得したパブリッシャーを購読することで結果を受け取ることができます。
@State var cancellable:AnyCancellable?
var body: some View {
Text("Hello")
.onAppear {
cancellable = getPublisher().sink { str in
print(str)
}
}
}
Futureはインスタンス化時に実行される
Futureの中にある処理は購読されたタイミングではなく、インスタンス化されたタイミングで実行されます。
let publisher = Future<String, Never>() { promise in
print("In Future")
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
promise(.success("成功したよ"))
}
}
print("Out Future")
let cancellable = publisher.sink { str in
print("Sink Future")
print(str)
}
出力結果
In Future
Out Future
// 2秒後
Sink Future
成功したよ
購読をしていないのに処理が実行されてしまうのは期待する動作と異なる場合が多いです。それ解消するにはDeferred
を使用すると解決できるようです。
let publisher = Deferred {
Future<String, Never>() { promise in
print("In Future")
DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
promise(.success("成功したよ"))
}
}
}
print("Out Future")
let cancellable = publisher.sink { str in
print("Sink Future")
print(str)
}
出力結果
Out Future
In Future
// 2秒後
Sink Future
成功したよ
【Swift】Combine.frameworkのFutureとDeferredと即時実行、遅延実行
まだまだ勉強中ですので間違っている点や至らぬ点がありましたら教えていただけると助かります。
ご覧いただきありがとうございました。