SessionManager的作用是用于創(chuàng)建各種請(qǐng)求。
1. MultipartFormDataEncodingResult輔助類型
MultipartFormDataEncodingResult用于表示編碼多表單的結(jié)果,是一個(gè)枚舉,并關(guān)聯(lián)了一些相關(guān)信息。
public enum MultipartFormDataEncodingResult {
case success(request: UploadRequest, streamingFromDisk: Bool, streamFileURL: URL?)
case failure(Error)
}
2. 屬性
// 默認(rèn)的SessionManager
open static let `default`: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
}()
// 默認(rèn)請(qǐng)求頭
open static let defaultHTTPHeaders: HTTPHeaders = {
}()
// 多表單編碼時(shí)使用的內(nèi)存臨界值, `10_000_000`下劃線使得讀者更容易讀
open static let multipartFormDataEncodingMemoryThreshold: UInt64 = 10_000_000
// 底層的URLSession
open let session: URLSession
// 底層URLSession的代理,session的所有代理都由它來(lái)處理
open let delegate: SessionDelegate
// 是否馬上開(kāi)啟請(qǐng)求,默認(rèn)是true
open var startRequestsImmediately: Bool = true
// 請(qǐng)求適配器
open var adapter: RequestAdapter?
// 請(qǐng)求重試器,由代理提供(如果想要請(qǐng)求失敗的時(shí)候重試,我們需要定義一個(gè)請(qǐng)求重試器)
open var retrier: RequestRetrier? {
get { return delegate.retrier }
set { delegate.retrier = newValue }
}
// 默認(rèn)是nil。如果設(shè)置了這個(gè)handler,SessionDelegate的 `sessionDidFinishEventsForBackgroundURLSession`會(huì)自動(dòng)執(zhí)行這個(gè)handler;
// 如果想要在這個(gè)handler執(zhí)行前去處理自己的event,
// 我們要重寫 `sessionDidFinishEventsForBackgroundURLSession`,然后手動(dòng)調(diào)用這個(gè)handler
open var backgroundCompletionHandler: (() -> Void)?
// 執(zhí)行隊(duì)列
let queue = DispatchQueue(label: "org.alamofire.session-manager." + UUID().uuidString)
3. 初始化
// 傳入`configuration`和`delegate`,創(chuàng)建SessionManager
public init(
configuration: URLSessionConfiguration = URLSessionConfiguration.default,
delegate: SessionDelegate = SessionDelegate(),
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
self.delegate = delegate
self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
// 傳入`session`和`delegate`,創(chuàng)建SessionManager(注意:session的delegate和傳入的delegate必須是同一個(gè))
public init?(
session: URLSession,
delegate: SessionDelegate,
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
guard delegate === session.delegate else { return nil }
self.delegate = delegate
self.session = session
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
// 上面兩個(gè)初始化器相同的一些初始化
private func commonInit(serverTrustPolicyManager: ServerTrustPolicyManager?) {
session.serverTrustPolicyManager = serverTrustPolicyManager
delegate.sessionManager = self
// 把`backgroundCompletionHandler`傳給`delegate.sessionDidFinishEventsForBackgroundURLSession`
// `[weak self] session`這里的`session`在closure里面沒(méi)有用到,為了代碼簡(jiǎn)潔,其實(shí)應(yīng)該用`_`代替的
delegate.sessionDidFinishEventsForBackgroundURLSession = { [weak self] session in
guard let strongSelf = self else { return }
DispatchQueue.main.async { strongSelf.backgroundCompletionHandler?() }
}
}
// 被回收了之后,使session失效
deinit {
session.invalidateAndCancel()
}
4. 數(shù)據(jù)請(qǐng)求
// 提供`URLConvertible`,創(chuàng)建數(shù)據(jù)請(qǐng)求
@discardableResult
open func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
{
var originalRequest: URLRequest?
do {
originalRequest = try URLRequest(url: url, method: method, headers: headers)
// 使用指定的`encoding`,把參數(shù)編碼到請(qǐng)求上
let encodedURLRequest = try encoding.encode(originalRequest!, with: parameters)
return request(encodedURLRequest)
} catch {
return request(originalRequest, failedWith: error)
}
}
// 提供`URLRequestConvertible`,創(chuàng)建數(shù)據(jù)請(qǐng)求
@discardableResult
open func request(_ urlRequest: URLRequestConvertible) -> DataRequest {
var originalRequest: URLRequest?
do {
originalRequest = try urlRequest.asURLRequest()
let originalTask = DataRequest.Requestable(urlRequest: originalRequest!)
// 這里其實(shí)是用傳進(jìn)來(lái)的urlRequest,創(chuàng)建了一個(gè)dataTask
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
// 創(chuàng)建DataRequest
let request = DataRequest(session: session, requestTask: .data(originalTask, task))
// 因?yàn)閐elegate可能要處理多個(gè)請(qǐng)求,作者使用Swift的下標(biāo)特性把請(qǐng)求記錄在delegate的requests字典
delegate[task] = request
if startRequestsImmediately { request.resume() }
return request
} catch {
return request(originalRequest, failedWith: error)
}
}
// 提供`URLRequest`和`error`,創(chuàng)建數(shù)據(jù)請(qǐng)求
// 解決url或者參數(shù)處理過(guò)程可能會(huì)跑出錯(cuò)誤的情況
private func request(_ urlRequest: URLRequest?, failedWith error: Error) -> DataRequest {
// 首先聲明一個(gè)關(guān)聯(lián)值為空的data類型的RequestTask
var requestTask: Request.RequestTask = .data(nil, nil)
// 如果urlRequest不為空,創(chuàng)建一個(gè)data類型的RequestTask
if let urlRequest = urlRequest {
let originalTask = DataRequest.Requestable(urlRequest: urlRequest)
requestTask = .data(originalTask, nil)
}
let underlyingError = error.underlyingAdaptError ?? error
let request = DataRequest(session: session, requestTask: requestTask, error: underlyingError)
// 如果自定了以重試器,并且error是適配過(guò)程中出現(xiàn)的error,那么允許重試
if let retrier = retrier, error is AdaptError {
allowRetrier(retrier, toRetry: request, with: underlyingError)
} else {
if startRequestsImmediately { request.resume() }
}
return request
}
關(guān)于Swift的下標(biāo)特性,可以訪問(wèn)【Swift 3.1】12 - 下標(biāo) (Subscripts)。
5. 下載請(qǐng)求 & 上傳請(qǐng)求 & Stream請(qǐng)求
這三個(gè)請(qǐng)求與數(shù)據(jù)請(qǐng)求的代碼大同小異,大家可以自己深入看看。如果有不懂的,歡迎留言,我看到了會(huì)盡力解答。
6. 重試請(qǐng)求
// 重試請(qǐng)求是否成功
func retry(_ request: Request) -> Bool {
// 如果請(qǐng)求沒(méi)有任務(wù),則重試失敗
guard let originalTask = request.originalTask else { return false }
do {
let task = try originalTask.task(session: session, adapter: adapter, queue: queue)
request.delegate.task = task // resets all task delegate data
request.retryCount += 1
request.startTime = CFAbsoluteTimeGetCurrent()
request.endTime = nil
task.resume()
return true
} catch {
request.delegate.error = error.underlyingAdaptError ?? error
return false
}
}
// 實(shí)現(xiàn)重試
private func allowRetrier(_ retrier: RequestRetrier, toRetry request: Request, with error: Error) {
// 需要重試的請(qǐng)求可能很多,使用異步隊(duì)列
DispatchQueue.utility.async { [weak self] in
guard let strongSelf = self else { return }
retrier.should(strongSelf, retry: request, with: error) { shouldRetry, timeDelay in
guard let strongSelf = self else { return }
guard shouldRetry else {
if strongSelf.startRequestsImmediately { request.resume() }
return
}
DispatchQueue.utility.after(timeDelay) {
guard let strongSelf = self else { return }
// 是否重試成功
let retrySucceeded = strongSelf.retry(request)
// 如果重試成功,更新delegate的requests字典
if retrySucceeded, let task = request.task {
strongSelf.delegate[task] = request
} else {
if strongSelf.startRequestsImmediately { request.resume() }
}
}
}
}
}
有任何問(wèn)題,歡迎大家留言!
歡迎加入我管理的Swift開(kāi)發(fā)群:536353151,本群只討論Swift相關(guān)內(nèi)容。
原創(chuàng)文章,轉(zhuǎn)載請(qǐng)注明出處。謝謝!