AFNetworking源碼!解析

版權地址: https://www.jianshu.com/p/5f8...
做者:有毒的程序猿
說明:八點鐘學院二期學員
學院學習連接: https://ke.qq.com/course/171725

前言ios

上海快30歲了月入3W, 爲何仍是焦慮?git

你焦慮, 是由於你月入三萬的姿式不對! 若是你月入三萬的組成是:月薪1萬, 另外四套房子租金兩萬, 絕對不會焦慮.github

clipboard.png

AFNetworking-github原文連接:https://github.com/AFNetworki...macos

介紹安全

這篇文章主要對AFNetworking的對外接口和請求處理文件進行閱讀, 會拿出裏面的優秀的技術點進行介紹.服務器

1、AFHTTPSessionManagercookie

AFHTTPSessionManager類主要是對外提供接口, 經過調用父類方法封裝一些經常使用接口.網絡

AFHTTPSessionManager繼承自AFURLSessionManager,而且實現了<NSSecureCoding, NSCopying>兩個協議,若是對這兩個協議想要深刻了解能夠進這些查看https://www.jianshu.com/p/c54...session

A.NSCoder架構

- (instancetype)initWithCoder:(NSCoder *)decoder;//解檔 擴展 經過XIB建立的一個nib文件,會調用相關類的這個方法- (void)encodeWithCoder:(NSCoder *)coder;//歸檔+ (BOOL)supportsSecureCoding;支持NSSecureCoding

B.clang warning

#pragma clang diagnostic push#pragma clang diagnostic ignored "-Wgnu"//code#pragma clang diagnostic pop

表示在這個區間裏忽略一些特定的clang的編譯警告,由於AFNetworking做爲一個庫被其餘項目引用,因此不能全局忽略clang的一些警告,只能在有須要的時候局部這樣作,因此常常見忽略-Wgnu警告的寫法;連接,http://nshipster.com/clang-di...

C.description

- (NSString *)description { return [NSString stringWithFormat:@"<%@: %p, baseURL: %@, session: %@, operationQueue: %@>", NSStringFromClass([self class]), self, [self.baseURL absoluteString], self.session, self.operationQueue];}

相信跟多人跟我同樣常常忽略description,它是NSObject
裏面帶的一個屬性,而且攜帶了一個方法- (NSString *)description. 它就是咱們打印對象時所顯示的內容,默認狀態下, 咱們好比打印一個類:

AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];NSLog(@"%@", manager);// 不重寫description<AFHTTPSessionManager: 0x6000001ccc60>// 重寫description以後輸出的使咱們自定製內容<AFHTTPSessionManager: 0x6000001ccc60, baseURL: (null), session: <__NSURLSessionLocal: 0x7faa8f706420>, operationQueue: <NSOperationQueue: 0x60400003cc60>{name = 'NSOperationQueue 0x60400003cc60'}>因此我大膽猜想其內部實現- (NSString *)description { return [NSString stringWithFormat:@"<%@:%p>", NSStringFromClass([self class]),&self]; }
注:這是寫框架的一些細節, 可讓使用者經過打印的方式更加具體的看到當前對象的一些狀態.

D.NSURLSessionConfiguration

NSURLSessionConfiguration系統提供了三種配置

[1]Configuration options for an NSURLSession. When a session iscreated, a copy of the configuration object is made - you cannot modify the configuration of a session after it has been created.

// 在建立Session對象時,能夠經過NSURLSessionConfiguration對象來配置Session.Session一旦配置完畢,你就不可以修改.

[2]The shared session uses the global singleton credential, cache
and cookie storage objects.

// Default Session 將cache以及credentials存儲於本地。

[3]An ephemeral session has no persistent disk storage for cookies,
cache or credentials.

// Ephemeral Session 則對數據更加保密安全一些,它不會向本地存儲任何信息,全部的cache、credentials 等存在內存中並和Session綁定,當Session銷燬時,全部的相關信息也同時自動銷燬。

[4]A background session can be used to perform networking operations on behalf of a suspended application, within certain constraints.

// Background Session可以使APP處於後臺時,數據繼續傳輸。其行爲與default Session相似,可是全部的數據傳輸均有一個獨立的進程來管理(非本APP)。同時Background Session也有一些功能上的限制。

下面三種配置的接口提供

@interface NSURLSessionConfiguration : NSObject <NSCopying>@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));

2、AFURLSessionManager

AFURLSessionManager這個類纔是對請求發送的核心類.它主要包括AFURLSessionManagerTaskDelegate、_AFURLSessionTaskSwizzling、AFURLSessionManager這三個對象.

<一>AFURLSessionManagerTaskDelegate

這個類分發處理了AFURLSessionManager主類的上傳,下載進度的管理,經過觀察task一些方法的變化,來獲得進度.並且還幫忙處理了

NSURLSessionTaskDelegate、NSURLSessionDataTaskDelegate和NSURLSessionDownloadTaskDelegate 等代理的返回數據.

A.NSProgress

// 進度暫停回調@property (nullable, copy) void (^pausingHandler)(void);// 進度恢復回調@property (nullable, copy) void (^resumingHandler)(void) NS_AVAILABLE(10_11, 9_0);注:AFNetworking 對進度的管理也用到了NSProgress,並實現了進度的暫停及恢復.

這裏(https://www.jianshu.com/p/239...

<二>_AFURLSessionTaskSwizzling

這個類在#issues 1477上reopen了屢次,討論仍是很激烈的。討論的起由是app會莫名crash,主要緣由是AFNetworking對NSURLSessionTask中的state進行了KVO操做。一開始人們removeObserver這個state,可是會形成AFNetworkActivityIndicatorManager功能(其中會觀察state)削弱。另外後來iOS8上也出現了一樣crash現象,貌似iOS7和iOS8在NSURLSessionTask有些不一樣。最後仍是有個大神用swizzling方法才解決了這個問題。
A.任務狀態監聽

AFNetworking巧妙的運用runtime的方法交換在+load中給NSURLSessionTask的兩個方法注入監聽.

  • (void)suspend;- (void)resume;

clipboard.png

AFNetworking源碼!解析

- (void)af_resume { NSAssert([self respondsToSelector:@selector(state)], @"Does not respond to state"); NSURLSessionTaskState state = [self state]; [self af_resume]; if (state != NSURLSessionTaskStateRunning) { // 這有點不明白這個討論恆成立state = NSURLSessionTaskStateCanceling; // 發送從新開始通知 用於網路指示器的設置 [[NSNotificationCenter defaultCenter] postNotificationName:AFNSURLSessionTaskDidResumeNotification object:self]; }}

<三>AFURLSessionManager

A.NSURLSession與NSURLConnection

NSURLSession在iOS7.0時被Apple提出後, 雖然Apple一直對其良好的API設計大力推廣,然而其可以達到的效果, 彷佛一直都和NSURLConnection不相伯仲.因爲AFNetworking優秀的架構設計, NSURLSession甚至還不如NSURLConnection好用.那麼,有什麼理由切換到NSURLSession? 2015年的WWDC彷佛告訴了咱們答案.HTTP /2, 2015年5月RFC 7540正式發表的下一代HTTP協議,是1999年來HTTP 1.1發佈後的首個更新. 相對於前一個版本, HTTP /2以快著稱.

clipboard.png

根據2015的WWDC Session71,咱們知道iOS9+,NSURLSession開始正式支持HTTP /2,也就意味着你的網絡鏈接速度也能夠有如上圖那樣的提高。

B.共享NSURLSession思路分析

如今AFNetworking 內部提供的建立方式[AFHTTPSessionManager manager],每次調用會新建一個NSURLSession,而後新建Task,激活Task,完成網絡請求。

在回答這個問題之前,咱們先來聊聊網絡的通信協議。咱們也都知道,HTTP協議是基於TCP協議的。因此在每次的HTTP請求以前,客戶端和服務器端,都先須要通過TCP鏈接的三次握手,即每次請求以前,網絡的數據都已經在客戶端和服務器端之間來回了三次。以下圖:

clipboard.png

事實上在HTTP 0.9, HTTP 1.0協議的時代,每次HTTP的請求,都須要先通過TCP的鏈接,而後纔開始HTTP的請求.那麼,爲了讓咱們的請求更快,避免每次都產生一個TCP三次握手,成了一個優化的選項。因而在HTTP 1.1中,出現了Connection: keep-alive這個選項。這個優化選項,可使得客戶端和服務器端複用一個TCP鏈接,從而減少每次的網絡請求時間。

沒錯,共享的NSURLSession將會複用TCP的鏈接,而每次都新建NSURLSession的操做將致使每次的網絡請求都開啓一個TCP的三次握手。因此咱們封裝請求類的時候,最好用單例模式.讓manager持有NSURLSession,達到共享的效果.即一個Session
建立多個Task來實現網路的請求.

B.delegate的儲存

self.mutableTaskDelegatesKeyedByTaskIdentifier 是一個儲存AFURLSessionManagerTaskDelegate的可變字典.用NSLock鎖保證了線程安全.

clipboard.png

C. responseSerializer

/* 當數據傳輸任務用「GET」、「POST」等方式時,在「dataTaskWithRequest:success:failure:」方法裏建立的一個從服務器發回的響應。 默認狀況下,此屬性設置爲「AFJSONResponseSerializer」的一個實例。 @warning 「responseSerializer」必須不爲空. / @property (nonatomic, strong) id <AFURLResponseSerialization> responseSerializer;
AFHTTPRequestSerializer 和AFHTTPResponseSerializer 都遵循了<AFURLResponseSerialization>協議.

爲何這裏提到這個呢, 這種經過協議來整合不一樣工具的方法,很值得借鑑. 在之後的文章中會詳細介紹這兩個類.

謝謝觀賞。

相關文章
相關標籤/搜索