Home > other >  Swift: execute an operation conditionally on Publisher
Swift: execute an operation conditionally on Publisher

Time:03-11

I'm using Combine for networking and I want to have some of the combine operations executed only if a certain condition is present, for instance if a local boolean variable needsDecoding is true I want to add .decode(type:,decoder:):

if (needsDecoding) {
   return URLSession.shared.dataTaskPublisher(for: request)
                .map(\.data)
                .decode(type: T.self, decoder: JSONDecoder())
                .eraseToAnyPublisher()
} else {
    return URLSession.shared.dataTaskPublisher(for: request)
                .map(\.data)
                .eraseToAnyPublisher()
}

That code above works but is it possible to conditionally add .decode() to the chain?

CodePudding user response:

Assume for the moment that we try to write a generic function that does the same thing, accepts some data and returns either a generic parsed type or the original data:

func conditionallyDecodeSomeData<T>(data:Data) -> What_Goes_Here? {
    ...
}

Your question is pretty similar to "What type should this function return". The answer is the type that is the most general superset of all possible results. That's probably Any. (though you want it in a Result monad so it's probably Result<Any, Error>). Using Any would work, but its a pretty bad 'code smell'

If you have a limited number of return types then you could create an enumerated type:

enum OperationResults {
    case justData(Data)
    case oneParsedResult(Result1)
    case anotherParsedResult(AnotherResult)
}

Then your Combine pipeline could produce AnyPublisher<OperationResults, Error>. But if you want something truly generic then you would probably have to use AnyPublisher<Any, Error> which is not satisfying.

  • Related