Alamofire-從一個(gè)簡(jiǎn)單的請(qǐng)求深入源代碼(2)

之前我們看完了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è) delegateserverTrustPolicyManager
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ò)了.

最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市嫡纠,隨后出現(xiàn)的幾起案子,更是在濱河造成了極大的恐慌税肪,老刑警劉巖,帶你破解...
    沈念sama閱讀 206,602評(píng)論 6 481
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡,警方通過(guò)查閱死者的電腦和手機(jī)崖咨,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 88,442評(píng)論 2 382
  • 文/潘曉璐 我一進(jìn)店門(mén),熙熙樓的掌柜王于貴愁眉苦臉地迎上來(lái)油吭,“玉大人,你說(shuō)我怎么就攤上這事署拟⊥裨祝” “怎么了?”我有些...
    開(kāi)封第一講書(shū)人閱讀 152,878評(píng)論 0 344
  • 文/不壞的土叔 我叫張陵推穷,是天一觀的道長(zhǎng)心包。 經(jīng)常有香客問(wèn)我,道長(zhǎng)馒铃,這世上最難降的妖魔是什么蟹腾? 我笑而不...
    開(kāi)封第一講書(shū)人閱讀 55,306評(píng)論 1 279
  • 正文 為了忘掉前任,我火速辦了婚禮区宇,結(jié)果婚禮上娃殖,老公的妹妹穿的比我還像新娘。我一直安慰自己议谷,他們只是感情好炉爆,可當(dāng)我...
    茶點(diǎn)故事閱讀 64,330評(píng)論 5 373
  • 文/花漫 我一把揭開(kāi)白布。 她就那樣靜靜地躺著,像睡著了一般芬首。 火紅的嫁衣襯著肌膚如雪赴捞。 梳的紋絲不亂的頭發(fā)上,一...
    開(kāi)封第一講書(shū)人閱讀 49,071評(píng)論 1 285
  • 那天郁稍,我揣著相機(jī)與錄音赦政,去河邊找鬼。 笑死耀怜,一個(gè)胖子當(dāng)著我的面吹牛昼钻,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播封寞,決...
    沈念sama閱讀 38,382評(píng)論 3 400
  • 文/蒼蘭香墨 我猛地睜開(kāi)眼然评,長(zhǎng)吁一口氣:“原來(lái)是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來(lái)了狈究?” 一聲冷哼從身側(cè)響起碗淌,我...
    開(kāi)封第一講書(shū)人閱讀 37,006評(píng)論 0 259
  • 序言:老撾萬(wàn)榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎抖锥,沒(méi)想到半個(gè)月后亿眠,有當(dāng)?shù)厝嗽跇?shù)林里發(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 43,512評(píng)論 1 300
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡磅废,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 35,965評(píng)論 2 325
  • 正文 我和宋清朗相戀三年纳像,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片拯勉。...
    茶點(diǎn)故事閱讀 38,094評(píng)論 1 333
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡竟趾,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出宫峦,到底是詐尸還是另有隱情岔帽,我是刑警寧澤,帶...
    沈念sama閱讀 33,732評(píng)論 4 323
  • 正文 年R本政府宣布导绷,位于F島的核電站犀勒,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏妥曲。R本人自食惡果不足惜贾费,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 39,283評(píng)論 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望檐盟。 院中可真熱鬧褂萧,春花似錦、人聲如沸遵堵。這莊子的主人今日做“春日...
    開(kāi)封第一講書(shū)人閱讀 30,286評(píng)論 0 19
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)。三九已至锡足,卻和暖如春波丰,著一層夾襖步出監(jiān)牢的瞬間,已是汗流浹背舶得。 一陣腳步聲響...
    開(kāi)封第一講書(shū)人閱讀 31,512評(píng)論 1 262
  • 我被黑心中介騙來(lái)泰國(guó)打工掰烟, 沒(méi)想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留,地道東北人沐批。 一個(gè)月前我還...
    沈念sama閱讀 45,536評(píng)論 2 354
  • 正文 我出身青樓纫骑,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親九孩。 傳聞我的和親對(duì)象是個(gè)殘疾皇子先馆,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 42,828評(píng)論 2 345

推薦閱讀更多精彩內(nèi)容