系统: 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:
- Chainable Request / Response Methods
- URL / JSON / plist Parameter Encoding
- Upload File / Data / Stream / MultipartFormData
- Download File using Request or Resume Data
- Authentication with URLCredential
- HTTP Response Validation
- Upload and Download Progress Closures with Progress
- cURL Command Output
- Dynamically Adapt and Retry Requests
- TLS Certificate and Public Key Pinning
- Network Reachability
- 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()
首先先建立URLRequest
, URLSession
, 接着创建 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
并创建了对象SessionDelegate
, SessionDelegate
处理所有类型的delegate的回调callbacks
,它们被 underlying URLSession
所创建.
SessionDelegate
可以灵活被控制,在网络请求过程当中. 比如重写closures
,去定制化授权authentication
, 后台background sessions
去处理事件, HTTP
重定向redirection
, 缓存结果caching results
…
总结
HTTP Request做了一下事情:
AF.request(...)
调用- 创建
Session
去初始化URLRequest
- 创建
DataRequest
- 可以创建拦截器RequestAdapter,或者没有拦截器
URLRequest
DataRequest
创建了dataTask
SessionDelegate
跟踪DataRequest
和dataTask
- 如果
startRequestsImmediately
是true
,Session
启动dataTask
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