上几篇介绍了
Alamofire
的SessionManager
,SessionDelegate
,Request
等等。请求之后,必然会响应。那就是我们本篇要讲解的Response
,它是什么?
一、Response的设计
Alamofire
常规使用:
SessionManager.default
.request(urlString)
.response { (response) in
print(response)
}
我们知道Alamofire
采用链式设计,那它是如何保证response
在request
请求完成后执行的呢?
public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self {
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)
}
}
return self
}
将response
的执行放到队列queue
self.queue = {
let operationQueue = OperationQueue()
operationQueue.maxConcurrentOperationCount = 1
operationQueue.isSuspended = true
operationQueue.qualityOfService = .utility
return operationQueue
}()
- 创建操作队列
operationQueue
-
operationQueue.maxConcurrentOperationCount = 1
串行队列 -
operationQueue.isSuspended = true
默认挂起
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let taskDidCompleteWithError = taskDidCompleteWithError {
taskDidCompleteWithError(session, task, error)
} else {
//此处省略......
queue.isSuspended = false
}
}
-
queue.isSuspended = false
请求完成的代理让队列执行. - 这样就可以保证
request
执行完成后才执行response
二、Response是什么?
response
分为四种:
- DefaultDataResponse
- DataResponse
- DefaultDownloadResponse
- DownloadResponse
我们会有疑惑,download
和upload
一般都是成对的,为什么之力没有upload
?因为upload
返回的只是普通的数据.
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)
public init(
request: URLRequest?,
response: HTTPURLResponse?,
data: Data?,
error: Error?,
timeline: Timeline = Timeline(),
metrics: AnyObject? = nil)
{
self.request = request
self.response = response
self.data = data
self.error = error
self.timeline = timeline
}
-
DefaultDataResponse
是结构体 - 从初始化方法可以看出
DefaultDataResponse
只是一个信息的保存者 - 传递到外界供用户使用
- 面向对象原则
dataResponse
创建时的参数data
和error
从哪里来的?
override var data: Data? {
if dataStream != nil {
return nil
} else {
return mutableData
}
}
data
其实是mutableData
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
if initialResponseTime == nil { initialResponseTime = CFAbsoluteTimeGetCurrent() }
if let dataTaskDidReceiveData = dataTaskDidReceiveData {
dataTaskDidReceiveData(session, dataTask, data)
} else {
if let dataStream = dataStream {
dataStream(data)
} else {
mutableData.append(data)
}
let bytesReceived = Int64(data.count)
totalBytesReceived += bytesReceived
let totalBytesExpected = dataTask.response?.expectedContentLength ?? NSURLSessionTransferSizeUnknown
progress.totalUnitCount = totalBytesExpected
progress.completedUnitCount = totalBytesReceived
if let progressHandler = progressHandler {
progressHandler.queue.async { progressHandler.closure(self.progress) }
}
}
}
是在代理方法didReceive data
放进去的。
而error
是在didCompleteWithError
保存的。
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let taskDidCompleteWithError = taskDidCompleteWithError {
taskDidCompleteWithError(session, task, error)
} else {
if let error = error {
if self.error == nil { self.error = error }
if
let downloadDelegate = self as? DownloadTaskDelegate,
let resumeData = (error as NSError).userInfo[NSURLSessionDownloadTaskResumeData] as? Data
{
downloadDelegate.resumeData = resumeData
}
}
queue.isSuspended = false
}
}
三、序列化器responseSerializer
这里我们就看看DefaultDataResponse
和DataResponse
的区别
1、DefaultDataResponse.
public func response(queue: DispatchQueue? = nil, completionHandler: @escaping (DefaultDataResponse) -> Void) -> Self {
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)
}
}
return self
}
DefaultDataResponse
初始化方法
public init(
request: URLRequest?,
response: HTTPURLResponse?,
data: Data?,
error: Error?,
timeline: Timeline = Timeline(),
metrics: AnyObject? = nil)
{
self.request = request
self.response = response
self.data = data
self.error = error
self.timeline = timeline
}
2、DataResponse
public func response(
queue: DispatchQueue? = nil,
responseSerializer: T,
completionHandler: @escaping (DataResponse) -> Void)
-> Self
{
delegate.queue.addOperation {
let result = responseSerializer.serializeResponse(
self.request,
self.response,
self.delegate.data,
self.delegate.error
)
var dataResponse = DataResponse(
request: self.request,
response: self.response,
data: self.delegate.data,
result: result,
timeline: self.timeline
)
dataResponse.add(self.delegate.metrics)
(queue ?? DispatchQueue.main).async { completionHandler(dataResponse) }
}
return self
}
DataResponse
初始化方法
public init(
request: URLRequest?,
response: HTTPURLResponse?,
data: Data?,
result: Result,
timeline: Timeline = Timeline())
{
self.request = request
self.response = response
self.data = data
self.result = result
self.timeline = timeline
}
-
DefaultDataResponse
,默认序列化。没指定序列化器,会返回默认的。 - 返回
DataResponse
,如果用户指定序列化器,就会返回序列化处理后的DataResponse
-
DataResponse
会包含Result
类型的result
,序列化后的数据
我们就用json
序列化器讲解一下:
SessionManager.default
.request(urlString)
.responseJSON { (jsonResponse) in
print(jsonResponse)
}
responseJSON
的实现:
public func responseJSON(
queue: DispatchQueue? = nil,
options: JSONSerialization.ReadingOptions = .allowFragments,
completionHandler: @escaping (DataResponse) -> Void)
-> Self
{
return response(
queue: queue,
responseSerializer: DataRequest.jsonResponseSerializer(options: options),
completionHandler: completionHandler
)
}
- 封装并返回了一个 response
-
DataRequest.jsonResponseSerializer(options: options),
序列的初始化
public static func jsonResponseSerializer(
options: JSONSerialization.ReadingOptions = .allowFragments)
-> DataResponseSerializer
{
return DataResponseSerializer { _, response, data, error in
return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
}
}
- 这里返回
DataResponseSerializer
类型的序列化器,参数是一个闭包,
其中参数就是一个闭包,保存在DataResponseSerializer
的serializeResponse
public static func serializeResponseJSON(
options: JSONSerialization.ReadingOptions,
response: HTTPURLResponse?,
data: Data?,
error: Error?)
-> Result
{
guard error == nil else { return .failure(error!) }
if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) }
guard let validData = data, validData.count > 0 else {
return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
}
do {
let json = try JSONSerialization.jsonObject(with: validData, options: options)
return .success(json)
} catch {
return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error)))
}
}
- 闭包带有一个返回值类型
Result
:Request.serializeResponseJSON
let result = responseSerializer.serializeResponse(
self.request,
self.response,
self.delegate.data,
self.delegate.error
)
在response
中直接调用responseSerializer.serializeResponse
初始化器,获得Result
public static func serializeResponseJSON(
options: JSONSerialization.ReadingOptions,
response: HTTPURLResponse?,
data: Data?,
error: Error?)
-> Result
{
guard error == nil else { return .failure(error!) }
if let response = response, emptyDataStatusCodes.contains(response.statusCode) { return .success(NSNull()) }
guard let validData = data, validData.count > 0 else {
return .failure(AFError.responseSerializationFailed(reason: .inputDataNilOrZeroLength))
}
do {
let json = try JSONSerialization.jsonObject(with: validData, options: options)
return .success(json)
} catch {
return .failure(AFError.responseSerializationFailed(reason: .jsonSerializationFailed(error: error)))
}
}
- json序列化器: JSONSerialization.jsonObject
- 根据序列化的结果返回 : .success(json) 或者 .failure(error)
四、总结
-
- 使用
.responseJSON
序列化器
- 使用
-
- 创建序列化器
- 3.将
response
添加到操作队列 - 4.当请求完成后,队列开始执行,
- 5.调用序列化器执行后返回
result
- 6.
response
回调返回response
响应数据