LoginSignup
37
20

More than 3 years have passed since last update.

【Swift】Combine.frameworkのFutureとDeferredと即時実行、遅延実行

Posted at

以前投稿した内容で
Combine.frameworkのFutureはインスタンスを生成した時点で
中のクロージャを実行させるということについて書きました。

https://qiita.com/shiz/items/f089c93bdebfaef2196f
https://developer.apple.com/documentation/combine/future

この場合
Subscribeをしていないのに処理が実行されてしまい
無駄にリソースを消費してしまう可能性や
副作用を起こして思わぬ動作をしてしまう可能性もあります。

そういう場合Deferredを活用する方法があります。

DeferredはinitでcreatePublisherというクロージャを受け取り
中でPublisherを生成します。
このクロージャはSubscribeした時に初めて実行されます。

検証

下記のコードをPlaygroundで実行して確認します。

まずFutureの場合


let futurePublisher = Future<String, Never> { promise in
    print("Future 実行")
    promise(.success("hello"))
}

この時点で

Future 実行

が出力されます。

一方Deferredの場合


let deferredPublisher = Deferred { () -> Just<String> in
    print("Deferred 実行")
    return Just("hello")
}

これだけ書いても何も実行されません。

Subscribeしてみると


let cancellable = deferredPublisher
    .sink(receiveCompletion: {
        print("receiveCompletion \($0)")
    }, receiveValue: {
        print("receiveValue \($0)")
    })
Deferred 実行
receiveValue hello
receiveCompletion finished

とSubscribeしてから
クロージャの中が実行されていることがわかります。

これを活用してFutureを遅延実行させる方法が
下記の動画でも紹介されています。


下記の例はFutureの特徴をよく表しているため引用させていただきました。

注意点として下記の例にある2番目の1729という値を受け取ることはありません。

Futureは値を一度受け取るとすぐにCompletionするため
受け取れるのは最初の42だけです。

動画では値を継続的に受け取りたいため
この後Custom Publisherの生成を行っています。


let aFutureInt = Deferred {
  Future<Int, Never> { callback in
    DispatchQueue.main.asyncAfter(deadline: .now() + 2) {
      print("Hello from inside the future!")
      callback(.success(42))
      callback(.success(1729))
    }
  }
}

※ この時点ではまだSubscribeしていないため
実行はされません。

まとめ

Deferredについて検証してみました。
Deferredを活用することで不必要な処理やセットアップなどが
実行されるリスクを減らすことができます。

またFutureを一緒に活用することで
非同期処理の遅延実行も実現することができることもわかりました。

しかし
Futureは値を一度して受け取らないという特徴を持っているため
使い方を知らないと

「あれっ?なんか思っていたのと違う」

となってしまう可能性もあるので注意が必要ですね😅

何か間違いなどございましたら教えていただけますとうれしいです🙇🏻‍♂️

37
20
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
37
20