Cancelling a Future

I am enjoying the Combine book so far. I work at a company where we develop SDKs. In our swift api, I am looking to use Future as a return type for async functions, it seems like a perfect fit.

However, I need to be able to cancel the code that is running in the future. In the book, for example, we wrote an async method like so:


    static func save(_ image: UIImage) -> Future<String, PhotoWriter.Error> {
        return Future { resolve in
            do {
                try PHPhotoLibrary.shared().performChangesAndWait {
                    let request = PHAssetChangeRequest.creationRequestForAsset(from: image)
                    guard let savedAssetID = request.placeholderForCreatedAsset?.localIdentifier else {
                        return resolve(.failure(.couldNotSavePhoto))
                    }
                    resolve(.success(savedAssetID))
                }
            } catch {
                resolve(.failure(.generic(error)))
            }
        }
    }

But what if the code that I’m running the future is “cancellable”, meaning it might be a few network requests and if the user cancels the subscription, or the subscription is dealloc’d, how can I cancel the network requests, or the async code that I have running?

I can’t figure out a way to be notified that the subscription to the future was cancelled.

Thanks

Reading further, it looks like you cancel with the handleEvents function:

...
.handleEvents(receiveCancel: {
  self.dismiss(animated: true)
})
.eraseToAnyPublisher()

@tourultimate Really glad you sorted it out! Cheers! :]

Hey @tourultimate - just wanted to share a quick point here.
Future is greedy - means that it doesn’t need a subscription to perform its work. As soon as it’s created, it will already start performing whatever work it wraps (e.g. a network request, or however). Later subscriptions will get the same result (e.g. shared resource) from that future, so each subscriber in this case doesn’t create their own work/resource.

In that sense, canceling a subscription to a Future might not help much since the work would be done as soon as it is init’d.

Finally, to cancel any cancelable you can either:

  1. Simply deallocate it so nothing is referencing it, which will cause it’s automatic cancelation; or
  2. Call its cancel() method (part of the Cancelable protocol)

Hope you’re enjoying the book!
Shai.

I’m also interested if there is a way to cancel a swift async Task started inside a Future.

return Future { resolve in
let task = Task {
// some async work
// resolve when done
}

// how can task.cancel() be used? :sweat_smile:
}