Asynchronous processing executed in Future in Swift Combine is sinking, but it is canceled in the middle

I was addicted to using Combine, so I will leave it as a memorandum.

problem

Set the closure (subscriber) by sink to the instance of Future, and when the asynchronous process is completed, perform the closure set by sink. I want to, but Subscribe is canceled before it completes.

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")
        })
        //Closure does not run
        .sink(receiveCompletion: { completion in
            print("completion:\(completion)")
        }, receiveValue: {
            
        })
    }

Debug console


receiveSubscription
receiveRequest
receiveCancel

Solutions

You need to keep the return value of the sink method in a variable or use the [store](https://developer.apple.com/documentation/combine/anycancellable/store(in:) -6cr9i) method.

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: {
            
        })
    }

Debug console


receiveSubscription
receiveRequest
receiveoutput
receiveCompletion
completion:finished

Cause

It seems that it will be canceled if AnyCancellable returned from sink is destroyed before the process implemented in Future is completed (promise () is called). When I read the official reference, it was quietly written in the "Return Value" section.

https://developer.apple.com/documentation/combine/future/sink(receivecompletion:receivevalue:)

Recommended Posts

Asynchronous processing executed in Future in Swift Combine is sinking, but it is canceled in the middle
[Swift] What is asynchronous processing?
Like function The part that is stuck in making it asynchronous
Ebean.update () is not executed in the inherited model.
Which is better, Kotlin or Java in the future?
In Swift, when JSON purge, it is passed in the snake case and troublesome coping method
The strong parameter is true, but for some reason it cannot be saved in the table.