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.