如何快速编写针对alamofire请求的通用包装?

时间:2019-04-19 14:11:20

标签: swift generics alamofire

如何为alamofire请求编写通用包装?

如何在以下代码中将POST和GET函数转换为Generic函数?

我需要具有通用的请求函数,这些函数根据接收到的数据类型显示不同的行为。

另外,响应可以是通用的吗?

我的非通用代码在下面有完整概述

import Foundation
import Alamofire
import SwiftyJSON
// for passing string body
extension String: ParameterEncoding {
    public func encode(_ urlRequest: URLRequestConvertible, with parameters: Parameters?) throws -> URLRequest {
        var request = try urlRequest.asURLRequest()
        request.httpBody = data(using: .utf8, allowLossyConversion: false)
        return request
    }
}
public class ConnectionManager {
    func Post (FirstName: String, LastName: String, NationalID: String, NationalCode: String, BirthDate: Date,Image: String,isFemale: Bool,Age:Int64,Avg:Double, completion: @escaping CompletionHandler) {
        let body: [String:Any] = [
            "FirstName":FirstName,
            "LastName": LastName,
            "NationalID": NationalID,
            "NationalCode": NationalCode,
            "BirthDate":BirthDate,
            "Image": Image,
            "isFemale": isFemale,
            "Age": Age,
            "Avg": Avg
        ]
        Alamofire.request(BASE_URL, method: .post, parameters: body, encoding: JSONEncoding.default, headers: HEADER).responseJSON { (response) in
            if response.response?.statusCode == 200 {
                guard let data = response.result.value else { return }
                print(data)
                completion(true)
            } else {
                print("error reg auth service")
                guard let er = response.result.value else { return }
                print(er)
                completion(false)
                debugPrint(response.result.error as Any)
            }
        }
    }
    func get(FirstName: String, LastName: String, NationalID: String, NationalCode: String, BirthDate: Date,Image: String,isFemale: Bool,Age:Int64,Avg:Double, completion: @escaping CompletionHandler) -> [Person] {
        let body: [String:Any] = [
            "FirstName":FirstName,
            "LastName": LastName,
            "NationalID": NationalID,
            "NationalCode": NationalCode,
            "BirthDate":BirthDate,
            "Image": Image,
            "isFemale": isFemale,
            "Age": Age,
            "Avg": Avg
        ]
        Alamofire.request(BASE_URL, method: .get, parameters: body, encoding: JSONEncoding.default, headers: HEADER).responseJSON { (response) in
            if response.response?.statusCode == 200 {
                print("no error login in authservice")
                guard let data = response.result.value else { return }
                print(data)
                completion(true)
            }
            else if response.response?.statusCode == 400  {
                print("error 400 login in authservice")
                guard let er = response.result.value else { return }
                print(er)
                debugPrint(response.result.error as Any)
                completion(false)
            } else {
                print("error ## login in authservice")
                guard let er = response.result.value else { return }
                print(er)
                debugPrint(response.result.error as Any)
                completion(false)
            }
        }
        return [Person]()
    }
}

1 个答案:

答案 0 :(得分:1)

最好的方法是使用URLRequestConvertible Alamofires协议并为每个API请求创建自己的协议和简单结构:


import Foundation
import Alamofire

protocol APIRouteable: URLRequestConvertible {
    var baseURL: String { get }
    var path: String { get }
    var method: HTTPMethod { get }
    var parameters: Parameters? { get }
    var encoding: ParameterEncoding { get }
}

extension APIRouteable {
    var baseURL: String { return URLs.baseURL }
    // MARK: - URLRequestConvertible
    func asURLRequest() throws -> URLRequest {
        let url = try baseURL.asURL().appendingPathComponent(path)
        var urlRequest = URLRequest(url: url)
        urlRequest.httpMethod = method.rawValue
        return try encoding.encode(urlRequest, with: parameters)
    }
}

和请求看起来像这样:

struct GetBooks: APIRouteable {
        var path: String
        var method: HTTPMethod
        var parameters: Parameters?
        var encoding: ParameterEncoding
    }

并在APIClient内部准备通用方法:

func perform<T: Decodable>(_ apiRoute: APIRouteable,
                 completion: @escaping (Result<T>) -> Void) {
        let dataRequest = session
            .request(apiRoute)
        dataRequest
            .validate(statusCode: 200..<300)
            .responseDecodable(completionHandler: {  [weak dataRequest] (response: DataResponse<T>) in
                dataRequest.map { debugPrint($0) }
                let responseData = response.data ?? Data()
                let string = String(data: responseData, encoding: .utf8)
                print("Repsonse string: \(string ?? "")")
                switch response.result {
                case .success(let response):
                    completion(.success(response))
                case .failure(let error):
                    completion(.failure(error))
                }
            })
    }

并使用它:

 func getBooks(completion: @escaping (Result<[Book]>) -> Void) {
        let getBooksRoute = APIRoute.GetBooks()
        perform(getBooksRoute, completion: completion)
    }