0

I'm trying to map a future I've received from one class to the new future with new output and failure. I've come up with a solution very similar to one proposed here: Mapping Swift Combine Future to another Future.

/// Extension to Combine's Future type
extension Future {
    /// Maps future result to new types
    ///
    /// - Parameters:
    ///     - _ transformOutput - transforms successful output from source Future to new output
    ///     - _ transformFailure - transforms failure from source Future to new failure
    ///
    /// - Returns: Future with new output and failure types
    func map<NewOutput, NewFailure: Error>(
        _ transformOutput: @escaping  (Output) -> Result<NewOutput, NewFailure>,
        _ transformFailure: @escaping (Failure) -> NewFailure) -> Future<NewOutput, NewFailure> {
        var cancellable: AnyCancellable?
        return Future<NewOutput, NewFailure> { promise in
            cancellable = self.sink(receiveCompletion: { completion in
                if case .failure(let error) = completion {
                    promise(.failure(transformFailure(error)))
                }
            }, receiveValue: { value in
                promise(transformOutput(value))
            })
        }
    }
}

The problem, I have is with cancellable which is destroyed when the program exits the map function. What would be the best solution to extend the lifespan of this variable? The only solution I've come up with is to return to AnyCancellable object along with the newly created future but it leads to problems with where to store it and when to delete it. Maybe someone here had similar problems and come up with some brilliant solution :D

  • 2
    Why don't you simply chain together the already existing `map` and `mapError` functions? Makes things a one-liner and also works on non-future related publishers – Schottky Jul 25 '21 at 14:46
  • @Schottky That is my plan B. The problem with using ```map``` and ```mapError``` is that they are not returning Future and since the code I'm working on is a library, I need to maintain backward compatibility. – Janusz Czornik Jul 25 '21 at 15:13
  • 3
    Sounds like the library authors made a bad design choice (returning `Future` instead of `AnyPublisher`) and should consider changing the API. – rob mayoff Jul 25 '21 at 16:42
  • Anyway, if you don't want to manage the `AnyCancellable`, then you can avoid creating one by [using `Subscribers.Sink` directly](https://stackoverflow.com/a/62048039/77567) instead of using the `sink` operator. – rob mayoff Jul 25 '21 at 16:45

0 Answers0