URLSession至关于管理一个请求的类,它涉及到URL/URLRequest/URLSessionConfiguration/URLSessionTask。经过这几个类的综合使用,咱们就能够很方便的建立请求javascript
let userTel = "13231852031"
let userPassword = "123456"
let defaultConfiguration = URLSessionConfiguration.default
let sessionWithoutADelegate = URLSession(configuration: defaultConfiguration)
if let url = URL(string: "http://127.0.0.1:8080/v1/login?usertel=\(userTel)&userpassword=\(userPassword)") {
(sessionWithoutADelegate.dataTask(with: url) { (data, response, error) in
if let error = error {
print("Error: \(error)")
} else if let response = response,
let data = data,
let string = String(data: data, encoding: .utf8) {
print("Response: \(response)")
print("DATA:\n\(string)\nEND DATA\n")
}
}).resume()
}复制代码
let defaultConfiguration = URLSessionConfiguration.default
let sessionWithoutADelegate = URLSession(configuration: defaultConfiguration)
let paramer: [String: String] = ["userTel":"13231852031","userPassword":"123456"]
if let url = URL(string: "http://127.0.0.1:8080/v1/register") {
var request = URLRequest.init(url: url)
request.httpMethod = "POST"
request.httpBody = try? JSONSerialization.data(withJSONObject: paramer, options: JSONSerialization.WritingOptions.prettyPrinted)
sessionWithoutADelegate.dataTask(with: request, completionHandler: { (data, response, error) in
if let error = error {
print("Error:\(error)")
}else if let response = response,
let data = data,
let string = String(data: data,encoding: .utf8){
print("Response: \(response)\n")
print("DATA:\(string)\n")
}
}).resume()
}复制代码
Alamofire.request("https://httpbin.org/get")复制代码
首先,文档中给出上面的一个例子,咱们能够看到很简单就发送了一个请求。接下来咱们能够看一下Alamofire是如何实现的request,经过跳转咱们能够看到该方法是实如今Alamofire.swift文件中:html
@discardableResult
public func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
{
return SessionManager.default.request(
url,
method: method,
parameters: parameters,
encoding: encoding,
headers: headers
)
}复制代码
首先该方法经过URLConvertible
协议来判断URL的有效性(如未无效URL会抛出Error),而后方法默认为GET,parameters参数默认为空,参数编码默认为URLEncoding.default,header默认为空。在该方法中又调用了SessionManager
,接下来咱们再跳转到SessionManager,在SessionManager中的request方法实现以下(因为方法较长下面代码只贴关键部分):java
do {
originalRequest = try URLRequest(url: url, method: method, headers: headers)
let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
return request(encodedURLRequest)
} catch {
return request(originalRequest, failedWith: error)
}复制代码
在上述实现中咱们能够看到,若是各项参数都没问题的话,它会进入do
代码块中request方法.
do中的request方法实现以下:ios
do {
originalRequest = try urlRequest.asURLRequest()
let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
let request = DataRequest(session: session, requestTask: .data(originalTask, task))
delegate[task] = request
if startRequestsImmediately { request.resume() }
return request
} catch {
return request(originalRequest, failedWith: error)
}复制代码
仍是在判断各项参数都正确后调用resume方法,在该方法中它会调用URLSessionTask的resume()
来启动该次请求。由此咱们能够看出虽然咱们只是调用这么简单的一句话,可是里面仍是由不少条件和逻辑的,只不过这一切Alamofire替咱们作了。git
上述的代码逻辑若是把全部的错误检查和判断逻辑简化掉,相似于下方的代码:github
let url = URL.init(string: "http://example.com")
let session = URLSession.shared
session.dataTask(with: url!).resume()复制代码
Alamofire默认有五种response handler:编程
Tip:上述五种response handler都没对返回数据的HTTPURLResponse作验证,Alamofire是经过Response Validation作验证的。json
Alamofire.request("https://httpbin.org/get").response { response in
}复制代码
ResponseSerialization.swift中的方法实现:swift
delegate.queue.addOperation {
(queue ?? DispatchQueue.main).async {
var dataResponse = DefaultDataResponse(
request: self.request,
response: self.response,
data: self.delegate.data,
error: self.delegate.error,
timeline: self.timeline
)
dataResponse.add(self.delegate.metrics)
completionHandler(dataResponse)
}复制代码
DefaultDataResponse
为结构体,包含request、response、data等数据。api
Alamofire不建议使用这种response serializers。
Alamofire.request("https://httpbin.org/get").responseData { response in
}复制代码
若是请求数据和解析数据的过程当中没有发生错误,它将返回一个Data类型的数据,Response的Result将会是.success。在该方法的实现源码中调用了responseSerializer: DataRequest.dataResponseSerializer()
序列化数据的方法
Alamofire.request("https://httpbin.org/get").responseString { response in
}复制代码
该Handler经过responseStringSerializer
将返回的Data数据转为String类型,若是没有错误发生,而且服务器数据成功转为String,response的Result将为.success而且值为String。
Alamofire.request("https://httpbin.org/get").responseJSON { response in
}复制代码
该handler经过调用jsonResponseSerializer
方法来转换数据类型,若没发生错误request同上
Tip:使用链式response包含几个handler,就会请求几回数据数据
Response handlers默认在主线程队列中执行,可是咱们能够提供一个自定义线程队列
默认状况下,Alamofire认为任何已完成的请求都是成功的,不管相应内容是什么。你能够在handler以前调用validate
来判断status code
Alamofire支持HTTP的GET、POST、DELETE等方法,并将这些方法声明为HTTPMethod
的enum
Alamofire提供三种参数编码方式URL,JSON和PropertyList
SessionManager.swift是Alamofire中比较重要的一个文件,它是URLSession的管理类,文件中是对request方法的具体实现。正是有该类才使得Alamofire发起一个请求很是简单。
经过源码咱们能够看见若是不设置URLSessionConfiguration,默认为URLSessionConfiguration.default
你也能够将URLSessionConfiguration修改成Background Configuration和Ephemeral Configuration
Requests能够被暂停(suspended)复位(resumed)和取消(cancelled)
随着APP的不断更新和迭代,构建网络层的通用模式很重要。如何路由你的request也是很是重要的一个部分。URLConvertible
和URLRequestConvertible
协议能够帮助你构建路由的通用部分
String, URL, 和URLComponents是默认遵照URLConvertible
协议的,因此你能够在request中写String, URL, 和URLComponents,它会自动检测request中的参数,根据参数类型找到相应的方法转为URL。你也能够根据文档中的例子来构造本身的路由
URLRequest默认遵照该协议,该协议用来构造URLRequest
@discardableResult
:此关键字表示修饰的方法没必要接受返回值Swift 3.0 中方法的返回值必须有接收不然会报警告,固然其实主要目的是为了不开发人员忘记接收返回值的状况,可是有些状况下确实不须要使用返回值可使用"_"接收来忽略返回值。固然你也能够增长@discardableResult声明,告诉编译器此方法能够不用接收返回值open
:open 一个元素在其余module中仍是能够被overridestatic
:在方法的func关键字以前加上关键字static或者class均可以用于指定类方法.不一样的是用class关键字指定的类方法能够被子类重写@escaping
至此,Alamofire的源码已经了解完,我在这里只是简单的了解一下Alamofire是如何实现最基本的GET和POST请求如何实现。能够看到,它经过几层包装实现了参数的校验、request支持String、URL和URLComponents三种方式。因为水平有限,对于它下载上传等功能的源码并无十分理解,因此在这并无写,你们有能力的能够自行查看源码。在Alamofire中比较重要的几个文件Alamofire.swift/Response.swift/SessionManager.swift/Request.swift。