Swift Combine: 如何指定tryMap(_:)的Error类型?

Swift Combine: How to specify the Error type of tryMap(_:)?

在 Combine 框架中,我们可以在使用 tryMap 时抛出通用 Error 协议类型。

但是,我们如何才能更具体地了解 Error 类型呢?

例如,

let publisher = urlSession.dataTaskPublisher(for: request).tryMap { (data, response) -> (Data, HTTPURLResponse) in
      guard let response = response as? HTTPURLResponse else {
        throw URLError(.cannotParseResponse)
      }
      return (data, response)
}

如何指定这个publisherError类型?我想使用 URLError 而不是 Error.

我在Combine框架中找到了方法setFailureType(to:)。但是,它不适用于 tryMap(_:)

setFailureType(to:)只是强制一个失败类型为Never的发布者的失败类型。 tryMap 总是使用 Error 作为错误类型,因为任何 Error 都可能在闭包体中被抛出,所以你需要使用 mapError 来强制使用 URLError 类型:

let map_error = publisher.mapError({ error -> URLError in
    switch (error) {
    case let url_error as URLError:
        return url_error
    default:
        return URLError(.unknown)
    }
})

您也可以使用 flatMap 完成此操作。这将允许您同时指定 OutputError 类型,如下所示:

struct SomeResponseType {
    let data: Data
    let response: HTTPURLResponse
}

let publisher = urlSession.dataTaskPublisher(for: request)
    .flatMap { (data, response) -> AnyPublisher<SomeResponseType, URLError > in
      guard let response = response as? HTTPURLResponse else {
        return Fail(error: URLError(.cannotParseResponse))
            .eraseToAnyPublisher()
      }
      return Just(SomeResponseType(data: data, response: response)
          .setFailureType(to: URLError)
          .eraseToAnyPublisher()
}