Search code examples
swiftcombinepublisher

Publisher extension for .sink


I've made an extension for Publisher to simplify sink, but my backend (not made by me) is messed up and I have a custom error that shouldn't be an error, and I want to return .success.

extension Publisher {
    func sinkToResult(_ result: @escaping ((Result<Self.Output, Self.Failure>) -> Void)) -> AnyCancellable {
        return sink(receiveCompletion: { completion in
            switch completion {
            case .failure(let error):
                if let error = error as? ApiError, let globalError = error.globalErrors.first, globalError.code == 2233 {
                    //Here i want to send something like return(.success(true))
                }
                result(.failure(error))
            case .finished:
                break
            }
        }, 
        receiveValue: { output in
            result(.success(output))
        })
    }
}

Can you help me to create a custom Output.Self type that I can return here?


Solution

  • I think you have a couple of options:

    enum MyResult<T> {
      case noError
      case object(T)
    }
    

    and then change func signature to: func sinkToResult(_ result: @escaping ((Result<MyResult<Self.Output>, Self.Failure>) -> Void)) -> AnyCancellable

    Or you can wrap Result and add your specific case:

    enum MyResult<Success, Failure: Error> {
      case noError
      case result(Result<Success, Failure>)
    }
    

    and change signature to: func sinkToResult(_ result: @escaping ((MyResult<Self.Output, Self.Failure>) -> Void)) -> AnyCancellable.

    Either way, I think it would be better to handle this directly when you perform the JSON decoding.