使用 Generics / Codable w/ API 响应 204 NO CONTENT
Using Generics / Codable w/ API response 204 NO CONTENT
我正在使用泛型和可编码 URLSession
。
当我收到来自 API 的响应时,我检查状态是否在 200 - 299 范围内并像这样解码数据
guard let data = data, let value = try? JSONDecoder().decode(T.self, from: data) else {
return completion(.error("Could not decode JSON response"))
}
completion(.success(value))
然后将其传递给完成处理程序,一切正常。
我有一个新端点,我也必须 POST 但是,这个端点 returns 没有内容主体的 204。
因此,我无法解码响应,就像我无法传入类型一样?
我的完成处理程序期望
enum Either<T> {
case success(T)
case error(String?)
}
并像这样打开我的响应 statusCode
case 204:
let value = String(stringLiteral: "no content")
return completion(.success(value))
产生
的错误
Member 'success' in 'Either<>' produces result of type 'Either',
but context expects 'Either<>'
我的API客户是
protocol APIClientProtocol: class {
var task: URLSessionDataTask { get set }
var session: SessionProtocol { get }
func call<T: Codable>(with request: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void
func requestRefreshToken<T: Codable>(forRequest failedRequest: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void
}
extension APIClientProtocol {
func call<T: Codable>(with request: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void {
task = session.dataTask(with: request, completionHandler: { [weak self] data, response, error in
guard error == nil else {
return completion(.error("An unknown error occured with the remote service"))
}
guard let response = response as? HTTPURLResponse else {
return completion(.error("Invalid HTTPURLResponse recieved"))
}
switch response.statusCode {
case 100...299:
guard let data = data else { return completion(.error("No data in response")) }
guard let value = try? JSONDecoder().decode(T.self, from: data) else { return completion(.error("Could not decode the JSON response")) }
completion(.success(value))
case 300...399: return completion(.error(HTTPResponseStatus.redirection.rawValue))
case 400: return completion(.error(HTTPResponseStatus.clientError.rawValue))
case 401: self?.requestRefreshToken(forRequest: request, completion: completion)
case 402...499: return completion(.error(HTTPResponseStatus.clientError.rawValue))
case 500...599: return completion(.error(HTTPResponseStatus.serverError.rawValue))
default:
return completion(.error("Request failed with a status code of \(response.statusCode)"))
}
})
task.resume()
}
}
使您的 Either
枚举成功类型可选
enum Either<T> {
case success(T?)
case error(String)
}
为 204
响应状态创建案例,传递 nil
case 204:
completion(.success(nil))
然后您可以使用 typealias
并创建类似
的通用内容
typealias NoContentResponse = Either<Bool>
然后您应该可以打开 NoContentResponse
。
我正在使用泛型和可编码 URLSession
。
当我收到来自 API 的响应时,我检查状态是否在 200 - 299 范围内并像这样解码数据
guard let data = data, let value = try? JSONDecoder().decode(T.self, from: data) else {
return completion(.error("Could not decode JSON response"))
}
completion(.success(value))
然后将其传递给完成处理程序,一切正常。
我有一个新端点,我也必须 POST 但是,这个端点 returns 没有内容主体的 204。
因此,我无法解码响应,就像我无法传入类型一样?
我的完成处理程序期望
enum Either<T> {
case success(T)
case error(String?)
}
并像这样打开我的响应 statusCode
case 204:
let value = String(stringLiteral: "no content")
return completion(.success(value))
产生
的错误Member 'success' in 'Either<>' produces result of type 'Either', but context expects 'Either<>'
我的API客户是
protocol APIClientProtocol: class {
var task: URLSessionDataTask { get set }
var session: SessionProtocol { get }
func call<T: Codable>(with request: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void
func requestRefreshToken<T: Codable>(forRequest failedRequest: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void
}
extension APIClientProtocol {
func call<T: Codable>(with request: URLRequest, completion: @escaping (Either<T>) -> Void) -> Void {
task = session.dataTask(with: request, completionHandler: { [weak self] data, response, error in
guard error == nil else {
return completion(.error("An unknown error occured with the remote service"))
}
guard let response = response as? HTTPURLResponse else {
return completion(.error("Invalid HTTPURLResponse recieved"))
}
switch response.statusCode {
case 100...299:
guard let data = data else { return completion(.error("No data in response")) }
guard let value = try? JSONDecoder().decode(T.self, from: data) else { return completion(.error("Could not decode the JSON response")) }
completion(.success(value))
case 300...399: return completion(.error(HTTPResponseStatus.redirection.rawValue))
case 400: return completion(.error(HTTPResponseStatus.clientError.rawValue))
case 401: self?.requestRefreshToken(forRequest: request, completion: completion)
case 402...499: return completion(.error(HTTPResponseStatus.clientError.rawValue))
case 500...599: return completion(.error(HTTPResponseStatus.serverError.rawValue))
default:
return completion(.error("Request failed with a status code of \(response.statusCode)"))
}
})
task.resume()
}
}
使您的 Either
枚举成功类型可选
enum Either<T> {
case success(T?)
case error(String)
}
为 204
响应状态创建案例,传递 nil
case 204:
completion(.success(nil))
然后您可以使用 typealias
并创建类似
typealias NoContentResponse = Either<Bool>
然后您应该可以打开 NoContentResponse
。