返回

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”;。谢谢你的帮助。

特别声明:以上内容(图片及文字)均为互联网收集或者用户上传发布,本站仅提供信息存储服务!如有侵权或有涉及法律问题请联系我们。
举报
评论区(0)
按点赞数排序
用户头像