之前我們看完了Alamofire.request
的函數(shù)簽名, 接下來(lái), 我們來(lái)看看里面的實(shí)現(xiàn)
Alamofire.request
request 函數(shù)簽名
request 函數(shù)實(shí)現(xiàn)
先來(lái)貼一下代碼
public func request(
_ url: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil)
-> DataRequest
{
return SessionManager.default.request(
url,
method: method,
parameters: parameters,
encoding: encoding,
headers: headers
)
}
可以看到, 這個(gè)方法其實(shí)只是簡(jiǎn)單的調(diào)用SessionManager.default.request
而已.
這里, 出現(xiàn)了一個(gè)新的類(lèi)型, SessionManager
和 返回值 DataRequest
我們下面先看看看 SessionManager
SessionManager
SessionManager
負(fù)責(zé)創(chuàng)建和管理請(qǐng)求, 并且在內(nèi)部也管理了一個(gè) URLSession 對(duì)象.
為了理解這個(gè)類(lèi)型, 我們先來(lái)看看, 如果使用原生的 URLSession
該怎么寫(xiě)代碼
var data: Data?
override func viewDidLoad() {
super.viewDidLoad()
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
let dataTask = session.dataTask(with: URL(string: "https://httpbin.org/get")!)
dataTask.resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
self.data = Data()
completionHandler(.allow)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
self.data?.append(data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let data = self.data, let string = String(data: data, encoding: String.Encoding.utf8) {
print(string)
}
}
可以看到, 整個(gè)流程就是首先創(chuàng)建一個(gè) session, 然后使用這個(gè) session 創(chuàng)建一個(gè) dataTask, 最后啟動(dòng)任務(wù), 就可以在代理中獲取到數(shù)據(jù).
看到這里, 我們?cè)倏纯粗暗拇a
SessionManager.default
可以看到, 我們是通過(guò)這種方式, 創(chuàng)建的一個(gè) SessionManager
先看看 default
這個(gè)屬性.
open static let `default`: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
}()
可以看到, 這里是使用默認(rèn)的URLSessionConfiguration 配置, 并在里面添加了一些請(qǐng)求頭. 并使用這個(gè)配置初始化SessionManager
.
既然這里有一個(gè)默認(rèn)的請(qǐng)求頭, 我們就來(lái)看看添加了哪些東西
open static let defaultHTTPHeaders: HTTPHeaders = {
// 設(shè)置編碼類(lèi)型(gzip)
// Accept-Encoding HTTP Header; see https://tools.ietf.org/html/rfc7230#section-4.2.3
let acceptEncoding: String = "gzip;q=1.0, compress;q=0.5"
// 設(shè)置語(yǔ)言
// Accept-Language HTTP Header; see https://tools.ietf.org/html/rfc7231#section-5.3.5
let acceptLanguage = Locale.preferredLanguages.prefix(6).enumerated().map { index, languageCode in
let quality = 1.0 - (Double(index) * 0.1)
return "\(languageCode);q=\(quality)"
}.joined(separator: ", ")
// 設(shè)置 ua
// User-Agent Header; see https://tools.ietf.org/html/rfc7231#section-5.5.3
// Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0`
let userAgent: String = {
if let info = Bundle.main.infoDictionary {
let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown"
let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown"
let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown"
let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
let osNameVersion: String = {
let version = ProcessInfo.processInfo.operatingSystemVersion
let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
let osName: String = {
#if os(iOS)
return "iOS"
.... 其他系統(tǒng)類(lèi)型
#endif
}()
return "\(osName) \(versionString)"
}()
let alamofireVersion: String = {
guard
let afInfo = Bundle(for: SessionManager.self).infoDictionary,
let build = afInfo["CFBundleShortVersionString"]
else { return "Unknown" }
return "Alamofire/\(build)"
}()
return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
}
return "Alamofire"
}()
可以看到, 主要是添加了Accept-Encoding
, Accept-Language
, User-Agent
這幾個(gè)請(qǐng)求頭.
接下來(lái), 我們看看這個(gè)類(lèi)的構(gòu)造函數(shù), 其實(shí)有兩個(gè)構(gòu)造函數(shù), 不過(guò)我們這里用到的是這一個(gè).
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)
}
可以看到, 這里除了configuration
這個(gè)參數(shù)外, 還有一個(gè) delegate
和 serverTrustPolicyManager
delegate
主要是起到一個(gè)接受事件, 以及處理數(shù)據(jù)的作用. 跟我們寫(xiě)原生的類(lèi)似. Alamofire 將代理單獨(dú)分到獨(dú)立的類(lèi)中處理, 并在有在其中將所有的代理回調(diào), 以閉包屬性的方式暴露出來(lái), 方便用戶自行處理事件. 具體的, 我們后面再細(xì)講, 這里先大致了解一下.
而serverTrustPolicyManager
則主要是為了處理證書(shū).
函數(shù)的主體中, 我們看到, 這里跟我們寫(xiě)原生代碼一樣, 創(chuàng)建了一個(gè) URLSession, 并將之前創(chuàng)建的代理類(lèi)作為代理.
接下來(lái), 調(diào)用了一個(gè) commonInit
方法繼續(xù)完成初始化.
commonInit
里面并沒(méi)有什么特別的東西, 這里就略過(guò)了.