Git ссылка: https://github.com/sahilmanchanda2/wrapper-class-for-alamofire
Вот моя версия (с использованием Alamofire 5.0.2 ):
import Foundation
import Alamofire
class NetworkCall : NSObject{
enum services :String{
case posts = "posts"
}
var parameters = Parameters()
var headers = HTTPHeaders()
var method: HTTPMethod!
var url :String! = "https://jsonplaceholder.typicode.com/"
var encoding: ParameterEncoding! = JSONEncoding.default
init(data: [String:Any],headers: [String:String] = [:],url :String?,service :services? = nil, method: HTTPMethod = .post, isJSONRequest: Bool = true){
super.init()
data.forEach{parameters.updateValue($0.value, forKey: $0.key)}
headers.forEach({self.headers.add(name: $0.key, value: $0.value)})
if url == nil, service != nil{
self.url += service!.rawValue
}else{
self.url = url
}
if !isJSONRequest{
encoding = URLEncoding.default
}
self.method = method
print("Service: \(service?.rawValue ?? self.url ?? "") \n data: \(parameters)")
}
func executeQuery<T>(completion: @escaping (Result<T, Error>) -> Void) where T: Codable {
AF.request(url,method: method,parameters: parameters,encoding: encoding, headers: headers).responseData(completionHandler: {response in
switch response.result{
case .success(let res):
if let code = response.response?.statusCode{
switch code {
case 200...299:
do {
completion(.success(try JSONDecoder().decode(T.self, from: res)))
} catch let error {
print(String(data: res, encoding: .utf8) ?? "nothing received")
completion(.failure(error))
}
default:
let error = NSError(domain: response.debugDescription, code: code, userInfo: response.response?.allHeaderFields as? [String: Any])
completion(.failure(error))
}
}
case .failure(let error):
completion(.failure(error))
}
})
}
}
Приведенный выше класс использует последнюю версию Alamofire (по состоянию на февраль 2020 года). Этот класс охватывает почти каждый метод HTTP с возможностью отправки данных в формате Application / JSON или обычном режиме. С этим классом вы получаете большую гибкость, и он автоматически преобразует ответ в ваш объект Swift.
Посмотрите на метод init этого класса:
data: [String, Any] = В этом случае вы поместите данные своей формы.
headers: [String: String] = Здесь вы можете отправлять пользовательские заголовки, которые хотите отправить, вместе с request
url = Здесь вы можете указать полный URL, вы можете оставить его пустым, если вы уже определили baseurl в классе. это удобно, когда вы хотите использовать REST-сервис, предоставленный третьей стороной. Примечание: если вы заполняете URL, тогда следующим параметром service должно быть nil
service: services = Это перечисление, определенное в самом NetworkClass. они служат конечными точками. Посмотрите в методе init, если URL-адрес равен nil, но служба не равна nil, то в конце базового URL-адреса добавляется полный URL-адрес, пример будет предоставлен.
method: HTTPMethod = здесь вы можете указать, какой метод HTTP должен использовать запрос.
isJSONRequest = по умолчанию установлено в значение true. если вы хотите отправить обычный запрос, установите для него значение false.
В методе init вы также можете указать общие данные или заголовки, которые вы хотите отправлять при каждом запросе, например номер версии вашего приложения, iOS Version et c
Теперь рассмотрим метод execute: это универсальная c функция, которая будет возвращать объект swift по вашему выбору, если ответ успешен. Он напечатает ответ в виде строки в случае, если не удалось преобразовать ответ в ваш быстрый объект. если код ответа не попадает в диапазон 200-299, то произойдет сбой, и вы получите полное описание отладки для получения подробной информации.
Использование:
говорит, что мы имеем следующую структуру:
struct Post: Codable{
let userId: Int
let id: Int
let title: String
let body: String
}
Обратите внимание на базовый URL, определенный в NetworkClass https://jsonplaceholder.typicode.com/
Пример 1. Отправка сообщения HTTP с типом содержимого Application / JSON
let body: [String : Any] = ["title": "foo",
"body": "bar",
"userId": 1]
NetworkCall(data: body, url: nil, service: .posts, method: .post).executeQuery(){
(result: Result<Post,Error>) in
switch result{
case .success(let post):
print(post)
case .failure(let error):
print(error)
}
}
вывод:
Service: posts
data: ["userId": 1, "body": "bar", "title": "foo"]
Post(userId: 1, id: 101, title: "foo", body: "bar")
HTTP 400 Запрос
NetworkCall (данные: ["email": "peter@klaven"], URL: "https://reqres.in/api/login", метод: .post, isJSONRequest: false) .executeQuery () {(result: Result) в результате переключения {case .success (let post): печать (post) case .failure (let error): print (error)}}
вывод:
Service: https://reqres.in/api/login
data: ["email": "peter@klaven"]
Error Domain=[Request]: POST https://reqres.in/api/login
[Request Body]:
email=peter%40klaven
[Response]:
[Status Code]: 400
[Headers]:
Access-Control-Allow-Origin: *
Content-Length: 28
Content-Type: application/json; charset=utf-8
Date: Fri, 28 Feb 2020 05:41:26 GMT
Etag: W/"1c-NmpazMScs9tOqR7eDEesn+pqC9Q"
Server: cloudflare
Via: 1.1 vegur
cf-cache-status: DYNAMIC
cf-ray: 56c011c8ded2bb9a-LHR
expect-ct: max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct"
x-powered-by: Express
[Response Body]:
{"error":"Missing password"}
[Data]: 28 bytes
[Network Duration]: 2.2678009271621704s
[Serialization Duration]: 9.298324584960938e-05s
[Result]: success(28 bytes) Code=400 "(null)" UserInfo={cf-ray=56c011c8ded2bb9a-LHR, Access-Control-Allow-Origin=*, Date=Fri, 28 Feb 2020 05:41:26 GMT, expect-ct=max-age=604800, report-uri="https://report-uri.cloudflare.com/cdn-cgi/beacon/expect-ct", Server=cloudflare, Etag=W/"1c-NmpazMScs9tOqR7eDEesn+pqC9Q", x-powered-by=Express, Content-Type=application/json; charset=utf-8, Content-Length=28, Via=1.1 vegur, cf-cache-status=DYNAMIC}
с пользовательскими заголовками
NetworkCall (data: ["username": "sahil. manchanda2@gmail.com"], заголовки: ["custom-header-key": "custom-header-value" "], url:" https://httpbin.org/post ", метод: .post) .executeQuery () {(result: Result) в результате переключения {case .success (let data): print (data) case. ошибка (пусть ошибка): печать (ошибка)}}
вывод:
Service: https://httpbin.org/post
data: ["username": "sahil.manchanda2@gmail.com"]
{
"args": {},
"data": "{\"username\":\"sahil.manchanda2@gmail.com\"}",
"files": {},
"form": {},
"headers": {
"Accept": "*/*",
"Accept-Encoding": "br;q=1.0, gzip;q=0.9, deflate;q=0.8",
"Accept-Language": "en;q=1.0",
"Content-Length": "41",
"Content-Type": "application/json",
"Custom-Header-Key": "custom-header-value",
"Host": "httpbin.org",
"User-Agent": "NetworkCall/1.0 (sahil.NetworkCall; build:1; iOS 13.2.2) Alamofire/5.0.2",
"X-Amzn-Trace-Id": "Root=1-5e58a94f-fab2f24472d063f4991e2cb8"
},
"json": {
"username": "sahil.manchanda2@gmail.com"
},
"origin": "182.77.56.154",
"url": "https://httpbin.org/post"
}
typeMismatch(Swift.String, Swift.DecodingError.Context(codingPath: [], debugDescription: "Expected to decode String but found a dictionary instead.", underlyingError: nil))
В последнем примере вы можете увидеть typeMismatch в конце, я пытался передать [String: Any] в executeQuery, но поскольку Any не подтверждает возможность кодирования, мне пришлось использовать String.