Search code examples
swiftcombine

How can I convert a publisher into a publisher with a different type


I'm very new to Combine so please excuse poor terminology.

I have a network request that returns a publisher of type <EulaModel, Error>.

Want I want to do is get that publisher and map it to a new publisher of <EulaEntity, Error>

My first attempt was to try and map the request result to the publisher type I want but my ignorance is preventing me from proceeding

The Error I get when attempting the map / transformation is

Cannot convert return expression of type 'Publishers.Map<AnyPublisher<EulaDataModel, ApiError>, AnyPublisher<EULAEntity, any Error>>' to return type 'AnyPublisher<EULAEntity, any Error>'

func termsAcceptanceStatus()-> AnyPublisher<EULAEntity, Error> {
    // signal is AnyPublisher<EulaDataModel, Error>
    let signal = networkService.sendRequest(router: EulaRouter.getEula).combineResponse(decodingType: EulaDataModel.self)
    // I want to somehow return <EulaEntity, Error>
    return signal.map {  name -> AnyPublisher<EULAEntity, Error> in
        return self
          .publisherConver(from: name)
          .eraseToAnyPublisher()
      }
}
func publisherConver(from data: EulaDataModel) -> AnyPublisher<EULAEntity, Error> {
    let entity = convertModel(model: data)
    return Just(entity).setFailureType(to: Error.self).eraseToAnyPublisher()
  }
func convertModel(model: EulaDataModel) -> EULAEntity {
    return EULAEntity(agreed: model.legalTermsAccepted)
}

Solution

  • You need to use map instead of flatMap. You simply want to transform each value emitted by the Publisher into another type - you don't want to create a new Publisher for each emitted element.

    func termsAcceptanceStatus()-> AnyPublisher<EULAEntity, Error> {
        let signal = networkService.sendRequest(router: EulaRouter.getEula).combineResponse(decodingType: EulaDataModel.self)
        return signal
          .map { convertModel(model: $0) }
          .eraseToAnyPublisher()
    }