0
2

More than 3 years have passed since last update.

Swift CombineにてFutureで実行している非同期処理をsinkしているのに途中でキャンセルされる

Posted at

Combineを使用する際にハマってしまったので、備忘録として残します。

問題

Futureのインスタンスにsinkしてクロージャ(サブスクライバ)を設定し、非同期処理が完了した際にsinkにて設定したクロージャの処理を行いたいのだが、完了する前にSubscribeがキャンセルされてしまう。

func start() {
        Future<Void, Error>{ promise in
            DispatchQueue.main.asyncAfter(deadline: .now() + 5.0){
                promise(.success(()))
            }
        }
        .handleEvents(receiveSubscription: { _ in
            print("receiveSubscription")
        }, receiveOutput: {
            print("receiveOutput")
        }, receiveCompletion: { _ in
            print("receiveCompletion")
        }, receiveCancel: {
            print("receiveCancel")
        }, receiveRequest: { _ in
            print("receiveRequest")
        })
        // クロージャが実行されない
        .sink(receiveCompletion: { completion in
            print("completion:\(completion)")
        }, receiveValue: {

        })
    }
デバッグコンソール
receiveSubscription
receiveRequest
receiveCancel

解決方法

sinkメソッドの返り値を変数に保持するか、storeメソッドを使用して保持する必要がある。

func start() {
        cancellable = Future<Void, Error>{ promise in
            DispatchQueue.main.asyncAfter(deadline: .now() + 5.0){
                promise(.success(()))
            }
        }
        .handleEvents(receiveSubscription: { _ in
            print("receiveSubscription")
        }, receiveOutput: {
            print("receiveoutput")
        }, receiveCompletion: { _ in
            print("receiveCompletion")
        }, receiveCancel: {
            print("receiveCancel")
        }, receiveRequest: { _ in
            print("receiveRequest")
        })
        .sink(receiveCompletion: { completion in
            print("completion:\(completion)")
        }, receiveValue: {

        })
    }
デバッグコンソール
receiveSubscription
receiveRequest
receiveoutput
receiveCompletion
completion:finished

原因

Future内に実装した処理が完了(promise()がコールされる)前にsinkから返却されたAnyCancellableが破棄されてしまうとキャンセルされてしまうみたい。
公式のリファレンスを読むと「Return Value」の部分にひっそりと書かれていた。

0
2
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
0
2