Swift组合处理HTTP状态代码错误



我正在阅读这篇文章:https://www.raywenderlich.com/4161005-mvvm-with-combine-tutorial-for-ios关于如何使用联合收割机的Ray Wenderlich。他们有一个例子,它从API获取数据,但不处理HTTP状态代码。我想添加它,但到目前为止我无法添加。

根据这个答案,您可以添加一个tryMap,但XCode开始显示错误,如:Generic parameter 'T' could not be inferred

代码下方:

extension WeatherFetcher: WeatherFetchable {
func weeklyWeatherForecast(
forCity city: String
) -> AnyPublisher<WeeklyForecastResponse, WeatherError> {
return forecast(with: makeWeeklyForecastComponents(withCity: city))
}
private func forecast<T>(
with components: URLComponents
) -> AnyPublisher<T, WeatherError> where T: Decodable {
guard let url = components.url else {
let error = WeatherError.network(description: "Couldn't create URL")
return Fail(error: error).eraseToAnyPublisher()
}
return session.dataTaskPublisher(for: URLRequest(url: url))
.mapError { error in
.network(description: error.localizedDescription)
}
.flatMap(maxPublishers: .max(1)) { pair in
decode(pair.data)
}
.eraseToAnyPublisher()
}
}

我试着添加

.tryMap { data, response in
guard let httpResponse = response as? HTTPURLResponse,
200..<300 ~= httpResponse.statusCode else {
switch (response as! HTTPURLResponse).statusCode {
case (400...499):
throw ServiceErrors.internalError((response as! HTTPURLResponse).statusCode)
default:
throw ServiceErrors.serverError((response as! HTTPURLResponse).statusCode)
}
}
return data
}

我认为您可以简单地用tryMap替换flatMap块。而不是从tryMap返回数据,它应该被解码T。因此return data行应该是return try JSONDecoder().decode(T.self, from: data)

private func forecast<T>(with components: URLComponents) -> AnyPublisher<T, WeatherError> where T: Decodable {
guard let url = components.url else {
let error = WeatherError.network(description: "Couldn't create URL")
return Fail(error: error).eraseToAnyPublisher()
}
return session.dataTaskPublisher(for: URLRequest(url: url))
.tryMap { data, response in
guard let httpResponse = response as? HTTPURLResponse,
200..<300 ~= httpResponse.statusCode else {
switch (response as! HTTPURLResponse).statusCode {
case (400...499):
throw ServiceErrors.internalError((response as! HTTPURLResponse).statusCode)
default:
throw ServiceErrors.serverError((response as! HTTPURLResponse).statusCode)
}
}
return try JSONDecoder().decode(T.self, from: data)
}
.mapError { error in
WeatherError() // some kind of error
}
.eraseToAnyPublisher()

}

最新更新