如何为alamofire请求编写通用包装器?
如何在以下代码中将POST和GET函数转换为通用函数?
我需要具有通用请求函数,根据收到的数据类型显示不同的行为。
此外,响应可以是通用的吗?
我的非通用代码在下面完整概述
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]()
}
}
最好的想法是使用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)
}