一.默认Response
-DefaultDataResponse
- 返回二进制数据
Data
,响应示例:
SessionManager.default.request(urlString).response { (response) in
print("\(response)")
}
- 查看源码:
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
}
- 在这里将
self.request
,self.response
,self.delegate.data
,self.delegate.error
,self.timeline
,整合成DefaultDataResponse
对象,同时将dataResponse
交给了DispatchQueue.main
主队列回调出去,方便用户在请求回调中处理UI事件。 - 很明显,
DefaultDataResponse
传递到外面的是原始的二进制数据,
class DataTaskDelegate: TaskDelegate, URLSessionDataDelegate {
var dataTask: URLSessionDataTask { return task as! URLSessionDataTask }
override var data: Data? {
if dataStream != nil {
return nil
} else {
return 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) }
}
}
}
- 在
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data)
方法,收到数据的时候,就将mutableData.append(data)
追加到了mutableData
中,然后通过response
中的completionHandler(dataResponse)
回调给用户。 - 至于
error
的传递和赋值,同上查找方法可知,在收到错误的时候,赋值self.error
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let taskDidCompleteWithError = taskDidCompleteWithError {
taskDidCompleteWithError(session, task, error)
} else {
if let error = 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
}
}
通过上面的分析,可能会有疑问,这么强大的框架,只是原封不动的把二进制数据传出来,会不会有点
low
? 查看其他的response
可知,Alamofire
还有针对响应数据的序列化操作
二. DataResponse
1. 自定义序列化器
- 此处自定义了
responseSerializer
序列化器,返回序列化后的数据Result<value>
SessionManager.default.request(urlString).response(responseSerializer: DataResponseSerializer<String>.init(serializeResponse: { (reques, response, data, error) -> Result<String> in
print("原始数据:\(String(describing: response ?? nil))")
return .success("请求数据成功")
})) { (dataResponse) in
print("\(dataResponse)")
}
SessionManager.default.request(urlString).response { (response) in
print("\(response)")
}
- 源码分析:
public func response<T: DataResponseSerializerProtocol>(
queue: DispatchQueue? = nil,
responseSerializer: T,
completionHandler: @escaping (DataResponse<T.SerializedObject>) -> Void)
-> Self
{
delegate.queue.addOperation {
let result = responseSerializer.serializeResponse(
self.request,
self.response,
self.delegate.data,
self.delegate.error
)
var dataResponse = DataResponse<T.SerializedObject>(
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
}
- 首先序列化数据,
let result = responseSerializer.serializeResponse
,返回Result<Value>
类型,通过局部变量result
保存:
public struct DataResponseSerializer<Value>: DataResponseSerializerProtocol {
public typealias SerializedObject = Value
public var serializeResponse: (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>
public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, Data?, Error?) -> Result<Value>) {
self.serializeResponse = serializeResponse
}
}
- 调用
DataResponse
整合数据,返回数据多了一个result
,这个就是我们序列化后的数据,然后将数据回调到主线程。由于我们自定义了序列化器,所以在外部序列化的时候,我们可以对返回的数据进行预处理,以满足我们的需求。
2.自带responseJSON
SessionManager.default
.request(urlString)
.response { (response) in
print(response)
}.responseJSON { (jsonResponse) in
print(jsonResponse)
}
- 源码分析:
public func responseJSON(
queue: DispatchQueue? = nil,
options: JSONSerialization.ReadingOptions = .allowFragments,
completionHandler: @escaping (DataResponse<Any>) -> Void)
-> Self
{
return response(
queue: queue,
responseSerializer: DataRequest.jsonResponseSerializer(options: options),
completionHandler: completionHandler
)
}
-
responseSerializer
传入DataRequest.jsonResponseSerializer(options: options)
序列化参数
public static func jsonResponseSerializer(
options: JSONSerialization.ReadingOptions = .allowFragments)
-> DataResponseSerializer<Any>
{
return DataResponseSerializer { _, response, data, error in
return Request.serializeResponseJSON(options: options, response: response, data: data, error: error)
}
}
- 继续
Request.serializeResponseJSON
public static func serializeResponseJSON(
options: JSONSerialization.ReadingOptions,
response: HTTPURLResponse?,
data: Data?,
error: Error?)
-> Result<Any>
{
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)))
}
}
- 有木有发现,我们自定义的序列化器和系统实现的
serializeResponseJSON
序列化如出一辙。本质上都是传入一个序列化参数,对数据进行处理。
三.DefaultDownloadResponse
和 DownloadResponse
DefaultDownloadResponse
public func response(
queue: DispatchQueue? = nil,
completionHandler: @escaping (DefaultDownloadResponse) -> Void)
-> Self
{
delegate.queue.addOperation {
(queue ?? DispatchQueue.main).async {
var downloadResponse = DefaultDownloadResponse(
request: self.request,
response: self.response,
temporaryURL: self.downloadDelegate.temporaryURL,
destinationURL: self.downloadDelegate.destinationURL,
resumeData: self.downloadDelegate.resumeData,
error: self.downloadDelegate.error,
timeline: self.timeline
)
downloadResponse.add(self.delegate.metrics)
completionHandler(downloadResponse)
}
}
return self
}
DownloadResponse
public func response<T: DownloadResponseSerializerProtocol>(
queue: DispatchQueue? = nil,
responseSerializer: T,
completionHandler: @escaping (DownloadResponse<T.SerializedObject>) -> Void)
-> Self
{
delegate.queue.addOperation {
let result = responseSerializer.serializeResponse(
self.request,
self.response,
self.downloadDelegate.fileURL,
self.downloadDelegate.error
)
var downloadResponse = DownloadResponse<T.SerializedObject>(
request: self.request,
response: self.response,
temporaryURL: self.downloadDelegate.temporaryURL,
destinationURL: self.downloadDelegate.destinationURL,
resumeData: self.downloadDelegate.resumeData,
result: result,
timeline: self.timeline
)
downloadResponse.add(self.delegate.metrics)
(queue ?? DispatchQueue.main).async { completionHandler(downloadResponse) }
}
return self
}
- 序列化
public struct DownloadResponseSerializer<Value>: DownloadResponseSerializerProtocol {
public typealias SerializedObject = Value
public var serializeResponse: (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<Value>
public init(serializeResponse: @escaping (URLRequest?, HTTPURLResponse?, URL?, Error?) -> Result<Value>) {
self.serializeResponse = serializeResponse
}
}
DefaultDownloadResponse
和DownloadResponse
,对于序列化的处理与DefaultDataResponse
和DataResponse
大同小异;
网友评论