Alamofire 5源码解析一: 执行HTTP Request

系统: Mac OS 10.14.6, XCode 11,swift 5.0
写作时间:2019-11-16

说明

iOS开发,平时用Alamofire进行网络请求,那么请求url,和RequestURL是怎么请求网络的呢?
本文基于Alamofire 5.0版本进行分析。从5.0开始Alamofire.request() 中的 Alamofire用枚举AF来代替,AF.request() . 因为Alamfire为包路径namespace,以前方法名跟包的名字是一样的,做了区分处理.

先来看看Alamofire的Features:

  1. Chainable Request / Response Methods
  2. URL / JSON / plist Parameter Encoding
  3. Upload File / Data / Stream / MultipartFormData
  4. Download File using Request or Resume Data
  5. Authentication with URLCredential
  6. HTTP Response Validation
  7. Upload and Download Progress Closures with Progress
  8. cURL Command Output
  9. Dynamically Adapt and Retry Requests
  10. TLS Certificate and Public Key Pinning
  11. Network Reachability
  12. Comprehensive Unit and Integration Test Coverage

Request第一印象

Request的语法不容易看到深层的调用,平时用url为参数:

let myURLString = "https://httpbin.org/get"
AF.request(myURLString).responseJSON { (response) in
	debugPrint(response)
     // do stuff with JSON or error
}

或者用URLRequest

let url = URL(string: "https://httpbin.org/get")!
let urlRequest = URLRequest(url: url)
AF.request(urlRequest).responseJSON { (response) in
	debugPrint(response)
    // do stuff with JSON or error
}

用Apple原生的api URLSession用法如下:

let url = URL(string: myURLString)!
let urlRequest = URLRequest(url: url)
let session = URLSession.shared
let task = session.dataTask(with: urlRequest) {
    (data, response, error) in
    // serialize JSON
    // do stuff with the JSON or error
}
task.resume()

首先先建立URLRequestURLSession, 接着创建 dataTask ,并调用方法resume() 去唤醒. 结束以后通过回调dataTask 告诉我们结果. 最后通过序列化JSONSerialization 把二进制Data转换为JSON,或者处理错误errors.

Alamofire实际上是封装了URLSession,所以Alamofire 也会创建dataTask,然后调用方法.resume() 去唤醒执行. 接下来就进一步揭露Alamofire 的神秘面纱.

Alamofire Request是什么?

AF.request(myURLString) 看看这个方法的源码实现是如何的? cmd-click或者 两个手指右键点击选择“Jump to Definition”.

/// Creates a `DataRequest` using `Session.default` to retrieve the contents of the specified `url` using the
    /// `method`, `parameters`, `encoding`, and `headers` provided.
    ///
    /// - Parameters:
    ///   - url:           The `URLConvertible` value.
    ///   - method:        The `HTTPMethod`, `.get` by default.
    ///   - parameters:    The `Parameters`, `nil` by default.
    ///   - encoding:      The `ParameterEncoding`, `URLEncoding.default` by default.
    ///   - headers:       The `HTTPHeaders`, `nil` by default.
    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
    ///
    /// - Returns: The created `DataRequest`.
    public static func request(_ url: URLConvertible,
                               method: HTTPMethod = .get,
                               parameters: Parameters? = nil,
                               encoding: ParameterEncoding = URLEncoding.default,
                               headers: HTTPHeaders? = nil,
                               interceptor: RequestInterceptor? = nil) -> DataRequest {
    return Session.default.request(url,
                                   method: method,
                                   parameters: parameters,
                                   encoding: encoding,
                                   headers: headers,
                                   interceptor: interceptor)
}

这个方法创建了DataRequest,可以组合其它组件,比如method , headers, 前置拦截器 RequestInterceptors 和 特殊转码的参数Encodable parameters. 这里的方法都调用SessionManager

还有另一种方式传了URLRequest参数,

/// Creates a `DataRequest` using `Session.default` to execute the specified `urlRequest`.
    ///
    /// - Parameters:
    ///   - urlRequest:    The `URLRequestConvertible` value.
    ///   - interceptor:   The `RequestInterceptor`, `nil` by default.
    ///
    /// - Returns: The created `DataRequest`.
    public static func request(_ urlRequest: URLRequestConvertible, interceptor: RequestInterceptor? = nil) -> DataRequest {
    return Session.default.request(urlRequest, interceptor: interceptor)
}

这个方法创建 DataRequest ,表示遵循了协议URLRequestConvertible. 这样子更加灵活。还有一个拦截器,也就是在逻辑的前面,中间,和后面可以做处理,比如日志记录,cookie增加等。

注释: request(...) 返回了 DataRequest. 这个class是继承于Alamofire.Request. Alamofire.Request 有一个便利的特色: debugDescription 返回 cURL 清单,相当于Alamofire request. 所以如果你的api的问题,可以在回调里增加调试代码debugPrint(request). 你就可以对比cURL 清单与API 文档, 分享给后端同学看看哪里有问题, 或者赞贴到Terminal,你可以微调脚本,看看发送参数信息.

Alamofire SessionManager是什么?

SessionManager是真正干活的, AF.request(...) 只是为了方便去调用 default SessionManager 的代码 SessionManager.default.request(...).

你也可以不用default的SessionManager ,如果用参数URLSessionConfiguration 去初始化你的session. 比如, 你可以创建一个后台任务background session,或者用一个默认的请求头default headers,让所有的网络请求都用相同的请求头.

细节请参看文档SessionManager docs.

SessionManager.default.request(…) 干了什么?

先看源码:

    /// Creates a `DataRequest` from a `URLRequest` created using the passed components and a `RequestInterceptor`.
    ///
    /// - Parameters:
    ///   - convertible: `URLConvertible` value to be used as the `URLRequest`'s `URL`.
    ///   - method:      `HTTPMethod` for the `URLRequest`. `.get` by default.
    ///   - parameters:  `Parameters` (a.k.a. `[String: Any]`) value to be encoded into the `URLRequest`. `nil` by default.
    ///   - encoding:    `ParameterEncoding` to be used to encode the `parameters` value into the `URLRequest`.
    ///                  `URLEncoding.default` by default.
    ///   - headers:     `HTTPHeaders` value to be added to the `URLRequest`. `nil` by default.
    ///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
    ///
    /// - Returns:       The created `DataRequest`.
    open func request(_ convertible: URLConvertible,
                      method: HTTPMethod = .get,
                      parameters: Parameters? = nil,
                      encoding: ParameterEncoding = URLEncoding.default,
                      headers: HTTPHeaders? = nil,
                      interceptor: RequestInterceptor? = nil) -> DataRequest {
    let convertible = RequestConvertible(url: convertible,
                                         method: method,
                                         parameters: parameters,
                                         encoding: encoding,
                                         headers: headers)

    return request(convertible, interceptor: interceptor)
}

可以看到创建了RequestConvertible 结构体,把convertible当做参数,调用方法request(convertible, interceptor: interceptor) 方法,这个方法返回肯定是DataRequest类。

首先看看RequestConvertible 结构体。

struct RequestConvertible: URLRequestConvertible {
    let url: URLConvertible
    let method: HTTPMethod
    let parameters: Parameters?
    let encoding: ParameterEncoding
    let headers: HTTPHeaders?

    func asURLRequest() throws -> URLRequest {
        let request = try URLRequest(url: url, method: method, headers: headers)
        return try encoding.encode(request, with: parameters)
    }
}

里面有一些个属性,和一个创建URLRequest的方法asURLRequest(), 方法对URLReques和parameters进行编码。都是系统方法,没有什么特别的。

接下来重点看看request(convertible, interceptor: interceptor)方法

/// Creates a `DataRequest` from a `URLRequestConvertible` value and a `RequestInterceptor`.
///
/// - Parameters:
///   - convertible: `URLRequestConvertible` value to be used to create the `URLRequest`.
///   - interceptor: `RequestInterceptor` value to be used by the returned `DataRequest`. `nil` by default.
///
/// - Returns:       The created `DataRequest`.
open func request(_ convertible: URLRequestConvertible, interceptor: RequestInterceptor? = nil) -> DataRequest {
    let request = DataRequest(convertible: convertible,
                              underlyingQueue: rootQueue,
                              serializationQueue: serializationQueue,
                              eventMonitor: eventMonitor,
                              interceptor: interceptor,
                              delegate: self)

    perform(request)

    return request
}

终于看到对象DataRequest的创建,中间看到对request的加工perform(request), 最后返回DataRequest.

继续深入对象DataRequest

/// Creates a `DataRequest` using the provided parameters.
///
/// - Parameters:
///   - id:                 `UUID` used for the `Hashable` and `Equatable` implementations. `UUID()` by default.
///   - convertible:        `URLRequestConvertible` value used to create `URLRequest`s for this instance.
///   - underlyingQueue:    `DispatchQueue` on which all internal `Request` work is performed.
///   - serializationQueue: `DispatchQueue` on which all serialization work is performed. By default targets
///                         `underlyingQueue`, but can be passed another queue from a `Session`.
///   - eventMonitor:       `EventMonitor` called for event callbacks from internal `Request` actions.
///   - interceptor:        `RequestInterceptor` used throughout the request lifecycle.
///   - delegate:           `RequestDelegate` that provides an interface to actions not performed by the `Request`.
init(id: UUID = UUID(),
     convertible: URLRequestConvertible,
     underlyingQueue: DispatchQueue,
     serializationQueue: DispatchQueue,
     eventMonitor: EventMonitor?,
     interceptor: RequestInterceptor?,
     delegate: RequestDelegate) {
    self.convertible = convertible

    super.init(id: id,
               underlyingQueue: underlyingQueue,
               serializationQueue: serializationQueue,
               eventMonitor: eventMonitor,
               interceptor: interceptor,
               delegate: delegate)
}

/// Default initializer for the `Request` superclass.
///
/// - Parameters:
///   - id:                 `UUID` used for the `Hashable` and `Equatable` implementations. `UUID()` by default.
///   - underlyingQueue:    `DispatchQueue` on which all internal `Request` work is performed.
///   - serializationQueue: `DispatchQueue` on which all serialization work is performed. By default targets
///                         `underlyingQueue`, but can be passed another queue from a `Session`.
///   - eventMonitor:       `EventMonitor` called for event callbacks from internal `Request` actions.
///   - interceptor:        `RequestInterceptor` used throughout the request lifecycle.
///   - delegate:           `RequestDelegate` that provides an interface to actions not performed by the `Request`.
init(id: UUID = UUID(),
     underlyingQueue: DispatchQueue,
     serializationQueue: DispatchQueue,
     eventMonitor: EventMonitor?,
     interceptor: RequestInterceptor?,
     delegate: RequestDelegate) {
    self.id = id
    self.underlyingQueue = underlyingQueue
    self.serializationQueue = serializationQueue
    self.eventMonitor = eventMonitor
    self.interceptor = interceptor
    self.delegate = delegate
}

初始化无非就是给属性赋值。所以重点还是在perform(request)的处理

func perform(_ request: DataRequest) {
    requestQueue.async {
        guard !request.isCancelled else { return }

        self.activeRequests.insert(request)

        self.performSetupOperations(for: request, convertible: request.convertible)
    }
}

/// `DispatchQueue` on which `URLRequest`s are created asynchronously. By default this queue uses `rootQueue` as its
/// `target`, but a separate queue can be used if request creation is determined to be a bottleneck. Always profile
/// and test before introducing an additional queue.
public let requestQueue: DispatchQueue

/// Set of currently active `Request`s.
var activeRequests: Set<Request> = []

在队列DispatchQueue中异步执行,把request加入到容器Set<Request>
封装还是挺严密的,主要逻辑还在方法self.performSetupOperations(for: request, convertible: request.convertible)

func performSetupOperations(for request: Request, convertible: URLRequestConvertible) {
    let initialRequest: URLRequest

    do {
        initialRequest = try convertible.asURLRequest()
        try initialRequest.validate()
    } catch {
        rootQueue.async { request.didFailToCreateURLRequest(with: error.asAFError(or: .createURLRequestFailed(error: error))) }
        return
    }

    rootQueue.async { request.didCreateInitialURLRequest(initialRequest) }

    guard !request.isCancelled else { return }

    guard let adapter = adapter(for: request) else {
        rootQueue.async { self.didCreateURLRequest(initialRequest, for: request) }
        return
    }

    adapter.adapt(initialRequest, for: self) { result in
        do {
            let adaptedRequest = try result.get()
            try adaptedRequest.validate()

            self.rootQueue.async {
                request.didAdaptInitialRequest(initialRequest, to: adaptedRequest)
                self.didCreateURLRequest(adaptedRequest, for: request)
            }
        } catch {
            self.rootQueue.async { request.didFailToAdaptURLRequest(initialRequest, withError: .requestAdaptationFailed(error: error)) }
        }
    }
}

这里分为三个部分讲解:
1. convertible.asURLRequest() 创建URLRequest ,简单校验GET的方法,不能有httpBody

func validate() throws {
    if method == .get, let bodyData = httpBody {
        throw AFError.urlRequestValidationFailed(reason: .bodyDataInGETRequest(bodyData))
    }
}

如果有错误则结束,在队列中异步处理错误信息

/// Root `DispatchQueue` for all internal callbacks and state update. **MUST** be a serial queue.
public let rootQueue: DispatchQueue

错误处理的函数

/// Called when initial `URLRequest` creation has failed, typically through a `URLRequestConvertible`.
///
/// - Note: Triggers retry.
///
/// - Parameter error: `AFError` thrown from the failed creation.
func didFailToCreateURLRequest(with error: AFError) {
    self.error = error

    eventMonitor?.request(self, didFailToCreateURLRequestWithError: error)

    callCURLHandlerIfNecessary()

    retryOrFinish(error: error)
}

处理逻辑:错误信息赋值,回调Callback()检查处理,重试处理。
callCURLHandlerIfNecessary()这里的内容会比较多,比如记录错误信息加锁UnfairLock类 > os_unfair_lock_t属性,错误信息描述cURLDescription(), 比如header, cookie, credential, sessionConfiguration等。

2. 没有拦截器RequestInterceptor, 则执行request的请求,这里是核心内容。

func didCreateURLRequest(_ urlRequest: URLRequest, for request: Request) {
    request.didCreateURLRequest(urlRequest)

    guard !request.isCancelled else { return }

    let task = request.task(for: urlRequest, using: session)
    requestTaskMap[request] = task
    request.didCreateTask(task)

    updateStatesForTask(task, request: request)
}

func updateStatesForTask(_ task: URLSessionTask, request: Request) {
    request.withState { state in
        switch state {
        case .initialized, .finished:
            // Do nothing.
            break
        case .resumed:
            task.resume()
            rootQueue.async { request.didResumeTask(task) }
        case .suspended:
            task.suspend()
            rootQueue.async { request.didSuspendTask(task) }
        case .cancelled:
            // Resume to ensure metrics are gathered.
            task.resume()
            task.cancel()
            rootQueue.async { request.didCancelTask(task) }
        }
    }
}

最终看到终极BOSS > URLSessionTask, 如果请求已经取消,则返回。创建RequestTask,最后调用task.resume(). 方法func didCreateURLRequest(_ urlRequest: URLRequest, for request: Request) 用了多态的特性,后面的adapter调用的是同一个方法。

/// Creates a `Session` from a `URLSessionConfiguration`.
///
/// - Note: This initializer lets Alamofire handle the creation of the underlying `URLSession` and its
///         `delegateQueue`, and is the recommended initializer for most uses.
///
/// - Parameters:
///   - configuration:            `URLSessionConfiguration` to be used to create the underlying `URLSession`. Changes
///                               to this value after being passed to this initializer will have no effect.
///                               `URLSessionConfiguration.af.default` by default.
///   - delegate:                 `SessionDelegate` that handles `session`'s delegate callbacks as well as `Request`
///                               interaction. `SessionDelegate()` by default.
///   - rootQueue:                Root `DispatchQueue` for all internal callbacks and state updates. **MUST** be a
///                               serial queue. `DispatchQueue(label: "org.alamofire.session.rootQueue")` by default.
///   - startRequestsImmediately: Determines whether this instance will automatically start all `Request`s. `true`
///                               by default. If set to `false`, all `Request`s created must have `.resume()` called.
///                               on them for them to start.
///   - requestQueue:             `DispatchQueue` on which to perform `URLRequest` creation. By default this queue
///                               will use the `rootQueue` as its `target`. A separate queue can be used if it's
///                               determined request creation is a bottleneck, but that should only be done after
///                               careful testing and profiling. `nil` by default.
///   - serializationQueue:       `DispatchQueue` on which to perform all response serialization. By default this
///                               queue will use the `rootQueue` as its `target`. A separate queue can be used if
///                               it's determined response serialization is a bottleneck, but that should only be
///                               done after careful testing and profiling. `nil` by default.
///   - interceptor:              `RequestInterceptor` to be used for all `Request`s created by this instance. `nil`
///                               by default.
///   - serverTrustManager:       `ServerTrustManager` to be used for all trust evaluations by this instance. `nil`
///                               by default.
///   - redirectHandler:          `RedirectHandler` to be used by all `Request`s created by this instance. `nil` by
///                               default.
///   - cachedResponseHandler:    `CachedResponseHandler` to be used by all `Request`s created by this instance.
///                               `nil` by default.
///   - eventMonitors:            Additional `EventMonitor`s used by the instance. Alamofire always adds a
///                               `AlamofireNotifications` `EventMonitor` to the array passed here. `[]` by default.
public convenience init(configuration: URLSessionConfiguration = URLSessionConfiguration.af.default,
                        delegate: SessionDelegate = SessionDelegate(),
                        rootQueue: DispatchQueue = DispatchQueue(label: "org.alamofire.session.rootQueue"),
                        startRequestsImmediately: Bool = true,
                        requestQueue: DispatchQueue? = nil,
                        serializationQueue: DispatchQueue? = nil,
                        interceptor: RequestInterceptor? = nil,
                        serverTrustManager: ServerTrustManager? = nil,
                        redirectHandler: RedirectHandler? = nil,
                        cachedResponseHandler: CachedResponseHandler? = nil,
                        eventMonitors: [EventMonitor] = []) {
    precondition(configuration.identifier == nil, "Alamofire does not support background URLSessionConfigurations.")

    let delegateQueue = OperationQueue(maxConcurrentOperationCount: 1, underlyingQueue: rootQueue, name: "org.alamofire.session.sessionDelegateQueue")
    let session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: delegateQueue)

    self.init(session: session,
              delegate: delegate,
              rootQueue: rootQueue,
              startRequestsImmediately: startRequestsImmediately,
              requestQueue: requestQueue,
              serializationQueue: serializationQueue,
              interceptor: interceptor,
              serverTrustManager: serverTrustManager,
              redirectHandler: redirectHandler,
              cachedResponseHandler: cachedResponseHandler,
              eventMonitors: eventMonitors)
}

这里强调一下OperationQueue(maxConcurrentOperationCount: 1, underlyingQueue: rootQueue, name: "org.alamofire.session.sessionDelegateQueue") 这里多线程执行,在同一时间只处理一个。
3. 有拦截器RequestInterceptor,则处理拦截器逻辑。这个拦截器做的好的地方,在于把所有处理的逻辑(实际上为代码块block)存起来. 定义为Result<URLRequest, Error>) -> Void. 包括两种类型的数组Set.

/// All `RequestAdapter`s associated with the instance. These adapters will be run until one fails.
public let adapters: [RequestAdapter]
/// All `RequestRetrier`s associated with the instance. These retriers will be run one at a time until one triggers retry.
public let retriers: [RequestRetrier]

一类为请求的拦截器,也就是在请求前、中、后插入逻辑

/// A type that can inspect and optionally adapt a `URLRequest` in some manner if necessary.
public protocol RequestAdapter {
    /// Inspects and adapts the specified `URLRequest` in some manner and calls the completion handler with the Result.
    ///
    /// - Parameters:
    ///   - urlRequest: The `URLRequest` to adapt.
    ///   - session:    The `Session` that will execute the `URLRequest`.
    ///   - completion: The completion handler that must be called when adaptation is complete.
    func adapt(_ urlRequest: URLRequest, for session: Session, completion: @escaping (Result<URLRequest, Error>) -> Void)
}

一类为重试逻辑

public protocol RequestRetrier {
    /// Determines whether the `Request` should be retried by calling the `completion` closure.
    ///
    /// This operation is fully asynchronous. Any amount of time can be taken to determine whether the request needs
    /// to be retried. The one requirement is that the completion closure is called to ensure the request is properly
    /// cleaned up after.
    ///
    /// - Parameters:
    ///   - request:    `Request` that failed due to the provided `Error`.
    ///   - session:    `Session` that produced the `Request`.
    ///   - error:      `Error` encountered while executing the `Request`.
    ///   - completion: Completion closure to be executed when a retry decision has been determined.
    func retry(_ request: Request, for session: Session, dueTo error: Error, completion: @escaping (RetryResult) -> Void)
}

SessionDelegate做了哪些事情?

在旧版本的request是加载在SessionDelegate的数组里面的

@discardableResult
open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
    var originalRequest: URLRequest?

    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)
    }
}

新版本的SessionDelegate做了扩展

/// Instance's `SessionDelegate`, which handles the `URLSessionDelegate` methods and `Request` interaction.
public let delegate: SessionDelegate

public init(session: URLSession,
                delegate: SessionDelegate,
                rootQueue: DispatchQueue,
                startRequestsImmediately: Bool = true,
                requestQueue: DispatchQueue? = nil,
                serializationQueue: DispatchQueue? = nil,
                interceptor: RequestInterceptor? = nil,
                serverTrustManager: ServerTrustManager? = nil,
                redirectHandler: RedirectHandler? = nil,
                cachedResponseHandler: CachedResponseHandler? = nil,
                eventMonitors: [EventMonitor] = []) {
    precondition(session.configuration.identifier == nil,
                 "Alamofire does not support background URLSessionConfigurations.")
    precondition(session.delegateQueue.underlyingQueue === rootQueue,
                 "Session(session:) initializer must be passed the DispatchQueue used as the delegateQueue's underlyingQueue as rootQueue.")

    self.session = session
    self.delegate = delegate
    self.rootQueue = rootQueue
    self.startRequestsImmediately = startRequestsImmediately
    self.requestQueue = requestQueue ?? DispatchQueue(label: "\(rootQueue.label).requestQueue", target: rootQueue)
    self.serializationQueue = serializationQueue ?? DispatchQueue(label: "\(rootQueue.label).serializationQueue", target: rootQueue)
    self.interceptor = interceptor
    self.serverTrustManager = serverTrustManager
    self.redirectHandler = redirectHandler
    self.cachedResponseHandler = cachedResponseHandler
    eventMonitor = CompositeEventMonitor(monitors: defaultEventMonitors + eventMonitors)
    delegate.eventMonitor = eventMonitor
    delegate.stateProvider = self
}

再次看看Session的初始化方法。delegate.eventMonitor = eventMonitor 表示事件监听器,delegate.stateProvider = self 表示状态监听器。startRequestsImmediately: Bool = true 发起网络请求,默认值为true。self.serializationQueue = serializationQueue ?? DispatchQueue(label: "\(rootQueue.label).serializationQueue", target: rootQueue) 结果序列化线程,设置默认值。

let delegateQueue = OperationQueue(maxConcurrentOperationCount: 1, underlyingQueue: rootQueue, name: "org.alamofire.session.sessionDelegateQueue")
let session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: delegateQueue)

URLSession创建配置的delegateQueue,名字为"org.alamofire.session.sessionDelegateQueue"

urlRequest.asURLRequest() 转换了传过来的URLRequest. 比如, 如果传过来URL字符串 https://grokswift.com, 最终转换成URLRequest, 默认为GET 请求,默认没有参数no parameters, 没有默认请求头no non-default headers, 没有编解码no encoding.

再次看看请求的核心方法

func didCreateURLRequest(_ urlRequest: URLRequest, for request: Request) {
    request.didCreateURLRequest(urlRequest)

    guard !request.isCancelled else { return }

    let task = request.task(for: urlRequest, using: session)
    requestTaskMap[request] = task
    request.didCreateTask(task)

    updateStatesForTask(task, request: request)
}

override func task(for request: URLRequest, using session: URLSession) -> URLSessionTask {
    let copiedRequest = request
    return session.dataTask(with: copiedRequest)
}

let task = request.task(for: urlRequest, using: session)并没有马上执行,而是放到了RequestTaskMap.requestsToTasks: [Request: URLSessionTask]字典中。

func updateStatesForTask(_ task: URLSessionTask, request: Request) {
    request.withState { state in
        switch state {
        case .initialized, .finished:
            // Do nothing.
            break
        case .resumed:
            task.resume()
            rootQueue.async { request.didResumeTask(task) }
        case .suspended:
            task.suspend()
            rootQueue.async { request.didSuspendTask(task) }
        case .cancelled:
            // Resume to ensure metrics are gathered.
            task.resume()
            task.cancel()
            rootQueue.async { request.didCancelTask(task) }
        }
    }
}

public func request(_ request: Request, didResumeTask task: URLSessionTask) {
    NotificationCenter.default.postNotification(named: Request.didResumeTaskNotification, with: request)
}

task.resume() 开始网络请求,并在线程中异步执行request.didResumeTask(task) . 最后发现是发送了通知。

如果startRequestsImmediately 的设置为false,会怎么处理呢?

如果startRequestsImmediately不是true, 那么请求就会被挂起,可以手动调用resume()启动请求。:

let myURLString = "https://httpbin.org/get"
let request = AF.request(myURLString)
    .responseJSON { response in
      // do stuff with the JSON or error
    }
request.resume()

SessionDelegate还能干啥?

默认情况下Alamofire 创建Session并创建了对象SessionDelegateSessionDelegate处理所有类型的delegate的回调callbacks,它们被 underlying URLSession 所创建.

SessionDelegate 可以灵活被控制,在网络请求过程当中. 比如重写closures ,去定制化授权authentication, 后台background sessions去处理事件, HTTP 重定向redirection, 缓存结果caching results

总结

HTTP Request做了一下事情:

  1. AF.request(...) 调用
  2. 创建Session去初始化URLRequest
  3. 创建DataRequest
  4. 可以创建拦截器RequestAdapter,或者没有拦截器URLRequest
  5. DataRequest 创建了dataTask
  6. SessionDelegate 跟踪DataRequestdataTask
  7. 如果startRequestsImmediatelytrue, Session 启动dataTask
  8. DataRequest会返回给调用者,如果 startRequestsImmediately 是 false (状态可能是pause或者 cancel )

这就是Alamofire发起了一个网络请求.

参考

https://grokswift.com/alamofire-how-requests/

https://github.com/Alamofire/Alamofire/blob/master/Documentation/Usage.md

https://github.com/Alamofire/Alamofire

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值