git 链接:https://github.com/sahilmanchanda2/wrapper-class-for-alamofire https://github.com/sahilmanchanda2/wrapper-class-for-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 年 2 月),该类涵盖了几乎所有 HTTP 方法,可以选择以应用程序/JSON 格式或普通格式发送数据。通过这个类,您可以获得很大的灵活性,它会自动将响应转换为您的 Swift 对象。
看一下这个类的init方法它有:
data: [String,Any] = 您将在其中放置表单数据。
headers: [String:String] = 在此您可以发送要与请求一起发送的自定义标头
url = 这里你可以指定完整的url,如果你已经在Class中定义了baseurl,你可以将其留空。当您想要使用第三方提供的 REST 服务时,它会很方便。注意:如果您填写的是 url,那么下一个参数 service 应该为 nil
service: services = 它是 NetworkClass 本身定义的枚举。这些作为端点。查看 init 方法,如果 url 为 nil 但服务不为 nil,那么它将附加在基本 url 的末尾以形成完整的 URL,将提供示例。
method: HTTPMethod = 此处您可以指定请求应使用哪种 HTTP 方法。
isJSONRequest = 默认设置为 true。如果你想发送普通请求,请将其设置为 false。
在 init 方法中,您还可以指定要随每个请求发送的通用数据或标头,例如您的应用程序版本号、iOS 版本等
现在看看执行方法:它是一个通用函数,如果响应成功,它将返回您选择的 swift 对象。如果无法将响应转换为 swift 对象,它将以字符串形式打印响应。如果响应代码不在 200-299 范围内,那么它将失败,并为您提供完整的调试描述以获取详细信息。
Usage:
假设我们有以下结构:
struct Post: Codable{
let userId: Int
let id: Int
let title: String
let body: String
}
注意 NetworkClass 中定义的基本 urlhttps://jsonplaceholder.typicode.com/ https://jsonplaceholder.typicode.com/
示例 1:发送内容类型为 Application/JSON 的 HTTP Post
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)
}
}
output:
Service: posts
data: ["userId": 1, "body": "bar", "title": "foo"]
Post(userId: 1, id: 101, title: "foo", body: "bar")
-
HTTP 400 请求
NetworkCall(数据:[“电子邮件”:“peter@klaven”],网址:“https://reqres.in/api/login https://reqres.in/api/login", 方法: .post, isJSONRequest: false).executeQuery(){
(结果:结果)中
切换结果{
案例.成功(让帖子):
打印(发布)
案例.失败(让错误):
打印(错误)
}
}
output:
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(数据: ["用户名":"[电子邮件受保护] /cdn-cgi/l/email-protection”],标头:[“自定义标头键”:“自定义标头值”],网址:“https://httpbin.org/post https://httpbin.org/post", 方法: .post).executeQuery(){(结果: 结果) 中
切换结果{
案例.成功(让数据):
打印(数据)
案例.失败(让错误):
打印(错误)
}
}
output:
Service: https://httpbin.org/post
data: ["username": "[email protected] /cdn-cgi/l/email-protection"]
{
"args": {},
"data": "{\"username\":\"[email protected] /cdn-cgi/l/email-protection\"}",
"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": "[email protected] /cdn-cgi/l/email-protection"
},
"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,我尝试在executeQuery 中传递 [String:Any],但由于 Any 无法确认可编码,所以我不得不使用 String。