1. 程式人生 > 其它 >Alamofire4.x開原始碼分析(五)進階用法

Alamofire4.x開原始碼分析(五)進階用法

2019獨角獸企業重金招聘Python工程師標準>>> hot3.png

Alamofire基於URLSession和Foundation URL的載入機制,為了更充分的瞭解和使用本框架,建議大家深刻的學習底層的網路實現.

建議閱讀

Session Manager

Alamofire.request就是我們最外層的方法方法,內部通過Alamofire.SessionManager和預設的URLSessionConfiguration實現

下面兩者是等價的

Alamofire.request("https://httpbin.org/get") 
let sessionManager = Alamofire.SessionManager.default
sessionManager.request("https://httpbin.org/get")

通過URLSessionConfiguration我們可以自由的修改http請求頭,超時時間等.應用程式可以未後臺和臨時會話建立管理器

Creating a Session Manager with Default Configuration

let configuration = URLSessionConfiguration.default
let sessionManager = Alamofire.SessionManager(configuration: configuration)

Creating a Session Manager with Background Configuration

let configuration = URLSessionConfiguration.background(withIdentifier: "com.example.app.background")
let sessionManager = Alamofire.SessionManager(configuration: configuration)

Creating a Session Manager with Ephemeral Configuration

let configuration = URLSessionConfiguration.ephemeral
let sessionManager = Alamofire.SessionManager(configuration: configuration)

自定義Session Configuration

var defaultHeaders = Alamofire.SessionManager.defaultHTTPHeaders
defaultHeaders["DNT"] = "1 (Do Not Track Enabled)"

let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = defaultHeaders

let sessionManager = Alamofire.SessionManager(configuration: configuration)

對於Authorization和Content-Type,不建議通過configuration來修改,Alamofire.request API提供的header來配置.

Session Delegate

預設情況下,Alamofire SessionManager會建立一個SessionDelegate物件來處理URLSession生成的所有各種回撥,從中抽出最簡單的實現方法. 對於特定需求的開發者,需要覆蓋這些方法. ####重寫閉包 第一種自定義SessionDelegate方法是重寫閉包,每個閉包都對應著SessionDelegate的實現. 舉例

/// Overrides default behavior for URLSessionDelegate method `urlSession(_:didReceive:completionHandler:)`.
open var sessionDidReceiveChallenge: ((URLSession, URLAuthenticationChallenge) -> (URLSession.AuthChallengeDisposition, URLCredential?))?

/// Overrides default behavior for URLSessionDelegate method `urlSessionDidFinishEvents(forBackgroundURLSession:)`.
open var sessionDidFinishEventsForBackgroundURLSession: ((URLSession) -> Void)?

/// Overrides default behavior for URLSessionTaskDelegate method `urlSession(_:task:willPerformHTTPRedirection:newRequest:completionHandler:)`.
open var taskWillPerformHTTPRedirection: ((URLSession, URLSessionTask, HTTPURLResponse, URLRequest) -> URLRequest?)?

/// Overrides default behavior for URLSessionDataDelegate method `urlSession(_:dataTask:willCacheResponse:completionHandler:)`.
open var dataTaskWillCacheResponse: ((URLSession, URLSessionDataTask, CachedURLResponse) -> CachedURLResponse?)?

以下是如何使用taskWillPerformHTTPRedirection避免重定向到任何apple.com的問題

let sessionManager = Alamofire.SessionManager(configuration: URLSessionConfiguration.default)
let delegate: Alamofire.SessionDelegate = sessionManager.delegate

delegate.taskWillPerformHTTPRedirection = { session, task, response, request in
    var finalRequest = request

    if
        let originalRequest = task.originalRequest,
        let urlString = originalRequest.url?.urlString,
        urlString.contains("apple.com")
    {
        finalRequest = originalRequest
    }

    return finalRequest
}

###子類覆蓋父類方法 另一種方法就是通過子類來重寫父類方法

class LoggingSessionDelegate: SessionDelegate {
    override func urlSession(
        _ session: URLSession,
        task: URLSessionTask,
        willPerformHTTPRedirection response: HTTPURLResponse,
        newRequest request: URLRequest,
        completionHandler: @escaping (URLRequest?) -> Void)
    {
        print("URLSession will perform HTTP redirection to request: \(request)")

        super.urlSession(
            session,
            task: task,
            willPerformHTTPRedirection: response,
            newRequest: request,
            completionHandler: completionHandler
        )
    }
}

####Request request,download, upload stream這四個方法的返回值分別為DataRequest, DownloadRequest, UploadRequest StreamRequest,並且他們都繼承自Request.每個子類都有專用的方法,如authenticate,validate,responseJSON和uploadProgress,都會返回呼叫者的例項,方便使用. Request可以被暫停,恢復,取消:

  • suspend() 暫停
  • resume() 恢復, 在SessionManager中有一個屬性:startRequestsImmediately。他控制這請求是不是立刻發起,預設的值為true。
  • cancel() 取消 同時該請求的每一個監聽物件都會受到一個錯誤回撥

####Routing Requests 隨著應用程式的擴充套件,在構建網路堆疊時,採用通用模式很重要. 該設計的重要部分是如何路由您的請求. Alamofire URLConvertible和URLRequestConvertible協議以及路由器設計模式就是為之設計的. 路由的概念就是中轉站的意思,在Alamofire中,String, URL, URLComponents實現了URLConvertible協議.

let urlString = "https://httpbin.org/post"
Alamofire.request(urlString, method: .post)

let url = URL(string: urlString)!
Alamofire.request(url, method: .post)

let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)!
Alamofire.request(urlComponents, method: .post)

採用URLConvertible協議的型別可用於構造URL,然後用於內部構造URL請求。 預設情況下,string,URL和URLComponent準守URLConvertible協議,允許將任何一個作為URL引數傳遞傳送請求,上傳和下載等方法:

let urlString = "https://httpbin.org/post"
Alamofire.request(urlString, method: .post)

let url = URL(string: urlString)!
Alamofire.request(url, method: .post)

let urlComponents = URLComponents(url: url, resolvingAgainstBaseURL: true)!
Alamofire.request(urlComponents, method: .post)

遵守URLConvertible協議,可以方便我們便捷的使用model與伺服器生成對映關係.

extension User: URLConvertible {
    static let baseURLString = "https://example.com"

    func asURL() throws -> URL {
    	let urlString = User.baseURLString + "/users/\(username)/"
        return try urlString.asURL()
    }
}
let user = User(username: "mattt")
Alamofire.request(user) // https://example.com/users/mattt

轉載於:https://my.oschina.net/roycehe/blog/1305425