Alamofire中Request和Response是关于网络请求请求响应,Request有四种类型data,download,upload和stream类型,stream只有在iOS9 之后才可以使用.
enum RequestTask {
case data(TaskConvertible?, URLSessionTask?)
case download(TaskConvertible?, URLSessionTask?)
case upload(TaskConvertible?, URLSessionTask?)
case stream(TaskConvertible?, URLSessionTask?)
}
Request
Request初始化,保存了原始的Task任务和结束的绝对时间.
init(session: URLSession, requestTask: RequestTask, error: Error? = nil) {
self.session = session
switch requestTask {
case .data(let originalTask, let task):
taskDelegate = DataTaskDelegate(task: task)
self.originalTask = originalTask
case .download(let originalTask, let task):
taskDelegate = DownloadTaskDelegate(task: task)
self.originalTask = originalTask
case .upload(let originalTask, let task):
taskDelegate = UploadTaskDelegate(task: task)
self.originalTask = originalTask
case .stream(let originalTask, let task):
taskDelegate = TaskDelegate(task: task)
self.originalTask = originalTask
}
delegate.error = error
delegate.queue.addOperation { self.endTime = CFAbsoluteTimeGetCurrent() }
}
TaskConvertible协议提供了一个接口返回URLSessionTask:
protocol TaskConvertible {
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask
}
open class DataRequest: Request {
// MARK: Helper Types
struct Requestable: TaskConvertible {
let urlRequest: URLRequest
func task(session: URLSession, adapter: RequestAdapter?, queue: DispatchQueue) throws -> URLSessionTask {
do {
let urlRequest = try self.urlRequest.adapt(using: adapter)
return queue.sync { session.dataTask(with: urlRequest) }
} catch {
throw AdaptError(error: error)
}
}
}
Response
Response中提供四个重要的结构体DefaultDataResponse ,DataResponse,DefaultDownloadResponse与DownloadResponse.
DataResponse扩展实现了CustomDebugStringConvertible协议,返回值的整体输出debugDescription.
extension DataResponse: CustomStringConvertible, CustomDebugStringConvertible {
/// The textual representation used when written to an output stream, which includes whether the result was a
/// success or failure.
public var description: String {
return result.debugDescription
}
/// The debug textual representation used when written to an output stream, which includes the URL request, the URL
/// response, the server data, the response serialization result and the timeline.
public var debugDescription: String {
var output: [String] = []
output.append(request != nil ? "[Request]: \(request!.httpMethod ?? "GET") \(request!)" : "[Request]: nil")
output.append(response != nil ? "[Response]: \(response!)" : "[Response]: nil")
output.append("[Data]: \(data?.count ?? 0) bytes")
output.append("[Result]: \(result.debugDescription)")
output.append("[Timeline]: \(timeline.debugDescription)")
return output.joined(separator: "\n")
}
}
Alamofire的开发中最常见的代码如下:
Alamofire.request("https://httpbin.org/get").responseJSON { response in
print("Request: \(String(describing: response.request))") // original url request
print("Response: \(String(describing: response.response))") // http url response
print("Result: \(response.result)") // response serialization result
if let json = response.result.value {
print("JSON: \(json)") // serialized json response
}
if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) {
print("Data: \(utf8Text)") // original server data as UTF8 string
}
}
responseJSON在Request和Response文件中都没有,将请求和响应的完美衔接的代码在ResponseSerialization.swift文件中.
extension DataRequest {
/// Creates a response serializer that returns a JSON object result type constructed from the response data using
/// `JSONSerialization` with the specified reading options.
///
/// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
///
/// - returns: A JSON object response serializer.
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)
}
}
/// Adds a handler to be called once the request has finished.
///
/// - parameter options: The JSON serialization reading options. Defaults to `.allowFragments`.
/// - parameter completionHandler: A closure to be executed once the request has finished.
///
/// - returns: The request.
@discardableResult
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
)
}
}
response函数实现代码:
extension DataRequest {
/// Adds a handler to be called once the request has finished.
///
/// - parameter queue: The queue on which the completion handler is dispatched.
/// - parameter completionHandler: The code to be executed once the request has finished.
///
/// - returns: The request.
@discardableResult
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
}
/// Adds a handler to be called once the request has finished.
///
/// - parameter queue: The queue on which the completion handler is dispatched.
/// - parameter responseSerializer: The response serializer responsible for serializing the request, response,
/// and data.
/// - parameter completionHandler: The code to be executed once the request has finished.
///
/// - returns: The request.
@discardableResult
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
}
}
Result
网络请求不管成功与否,最终都会有响应结果,Alamofire中的网络请求结果通过Result泛型枚举来表示.
public enum Result<Value> {
case success(Value)
case failure(Error)
/// Returns `true` if the result is a success, `false` otherwise.
public var isSuccess: Bool {
switch self {
case .success:
return true
case .failure:
return false
}
}
/// Returns `true` if the result is a failure, `false` otherwise.
public var isFailure: Bool {
return !isSuccess
}
/// Returns the associated value if the result is a success, `nil` otherwise.
public var value: Value? {
switch self {
case .success(let value):
return value
case .failure:
return nil
}
}
/// Returns the associated error value if the result is a failure, `nil` otherwise.
public var error: Error? {
switch self {
case .success:
return nil
case .failure(let error):
return error
}
}
}
Result结果解包:
public func unwrap() throws -> Value {
switch self {
case .success(let value):
return value
case .failure(let error):
throw error
}
}
Result扩展的map,flatMap函数:
public func map<T>(_ transform: (Value) -> T) -> Result<T> {
switch self {
case .success(let value):
return .success(transform(value))
case .failure(let error):
return .failure(error)
}
}
/// Evaluates the specified closure when the `Result` is a success, passing the unwrapped value as a parameter.
///
/// Use the `flatMap` method with a closure that may throw an error. For example:
///
/// let possibleData: Result<Data> = .success(Data(...))
/// let possibleObject = possibleData.flatMap {
/// try JSONSerialization.jsonObject(with: $0)
/// }
///
/// - parameter transform: A closure that takes the success value of the instance.
///
/// - returns: A `Result` containing the result of the given closure. If this instance is a failure, returns the
/// same failure.
public func flatMap<T>(_ transform: (Value) throws -> T) -> Result<T> {
switch self {
case .success(let value):
do {
return try .success(transform(value))
} catch {
return .failure(error)
}
case .failure(let error):
return .failure(error)
}
}
Swift水平有限,如有不当,欢迎多多指正~