ios-Alamofire与Swift Combine
发布时间:2022-03-08 20:41:41 529
相关标签: # android
我正在尝试用Alamofire实现联合框架。但是我在泛型方面有问题,你能帮我改进代码吗。我的同学们:
import Alamofire
import Foundation
public protocol APIConfiguration: URLRequestConvertible {
var method: HTTPMethod { get }
var baseURL: String { get }
var path: String { get }
var parameters: Parameters? { get }
func asURLRequest() throws -> URLRequest
}
public enum APIRouter: APIConfiguration {
case getPopularRequests
case getRegionAndCity
case getCities
case getComparableCities
case getSuggests(_ parameters: [String: String])
case getDrugs(_ parameters: [String: String])
// MARK: - HTTPMethod
public var method: HTTPMethod {
switch self {
case .getPopularRequests:
return .get
case .getRegionAndCity:
return .get
case .getCities:
return .get
case .getComparableCities:
return .get
case .getSuggests:
return .get
case .getDrugs:
return .get
}
}
// MARK: - BaseURL
public var baseURL: String {
return "https://example.com/api"
}
// MARK: - Path
public var path: String {
switch self {
case .getPopularRequests:
return "/goods/search/popular"
case .getRegionAndCity:
return "/handbooks/cities?q=&intersect_operation=&need_data=true&need_count=true&take=1000&skip=0&sort_by=name&sort_direction=asc"
case .getCities:
return "/handbooks/cities/"
case .getComparableCities:
return "/handbooks/cities?q=&intersect_operation=&need_data=true&need_count=true&take=1000&skip=0&sort_by=name&sort_direction=asc"
case .getSuggests:
return "/goods/search/suggests"
case .getDrugs:
return "/goods/search/global"
}
}
// MARK: - Parameters
public var parameters: Parameters? {
switch self {
case .getPopularRequests:
return nil
case .getRegionAndCity:
return nil
case .getCities:
return nil
case .getComparableCities:
return nil
case .getSuggests(let parameters):
return parameters
case .getDrugs(let parameters):
return parameters
}
}
// MARK: - URLRequestConvertible
public func asURLRequest() throws -> URLRequest {
let urlWithPathValue = baseURL + path
var url = try urlWithPathValue.asURL()
var urlRequest = URLRequest(url: url)
urlRequest.addValue("application/json", forHTTPHeaderField: "Content-Type")
urlRequest.httpMethod = method.rawValue
if let parameters = parameters {
switch self {
case .getPopularRequests, .getRegionAndCity, .getCities, .getComparableCities:
return urlRequest
case .getSuggests, .getDrugs:
var urlComponents = URLComponents(string: urlWithPathValue)!
urlComponents.queryItems = []
_ = parameters.map { (key, value) in
let item = URLQueryItem(name: key, value: value as? String)
urlComponents.queryItems?.append(item)
}
url = urlComponents.url!
urlRequest.url = url
}
}
return urlRequest
}
}
我有API客户端类:
public protocol APIPharmixCitiesScreenClientProtocol: AnyObject {
func getCities(completion: @escaping (Result) -> Void)
func getCitiesWithCombine() -> AnyPublisher, Never>
}
public final class APIClient {
@discardableResult
private func performRequest(route: APIRouter, decoder: JSONDecoder = JSONDecoder(), completion: @escaping (Result) -> Void) -> DataRequest {
return AF.request(route).responseDecodable(of: T.self, decoder: decoder) { response in
completion(response.result)
}
}
private func performCombineRequest(route: APIRouter, decoder: JSONDecoder = JSONDecoder()) -> AnyPublisher, Never> {
return AF.request(route).publishDecodable(type: T.self, decoder: decoder).result()
}
}
// MARK: - APIPharmixCitiesScreenClientProtocol
extension APIClient: APIPharmixCitiesScreenClientProtocol {
public func getCities(completion: @escaping (Result) -> Void) {
let jsonDecoder = JSONDecoder()
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
performRequest(route: .getCities, decoder: jsonDecoder, completion: completion)
}
public func getCitiesWithCombine() -> AnyPublisher, Never> {
let jsonDecoder = JSONDecoder()
jsonDecoder.keyDecodingStrategy = .convertFromSnakeCase
performCombineRequest(route: .getCities, decoder: jsonDecoder)
// return AF.request(APIRouter.getCities).publishDecodable(type: PharmixCitiesScreenModel.self, decoder: jsonDecoder).result()
}
}
我计划这样使用:
APIClient().getCitiesWithCombine()
.receive(on: DispatchQueue.main)
.sink { [weak self] result in
switch result {
case .success(let data):
self?.prepareTableViewModel(for: data.data.elements)
self?.requestError = nil
case .failure(let error):
self?.requestError = error
}
}
.store(in: &cancellables)
当我使用这行代码时
return AF.request(APIRouter.getCities).publishDecodable(type: PharmixCitiesScreenModel.self, decoder: jsonDecoder).result()
,但如果我尝试
performCombineRequest(route: .getCities, decoder: jsonDecoder)
我得到了;无法推断泛型参数“T”;。谢谢你的帮助。
特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报