iOS (五) - AFNetworking 3.0+ 總結NSURLSession (2)

隨說 : 從解決業(yè)務方法中入手開始讀源碼,但是在此之前,我有個問題,為什么蘋果在iOS7之后引進了這個NSURLSession? ,并且AFNetworking3.x后已經(jīng)將NSURLConnection廢棄,我有個原則,你會用一個東西去解決一些問題之后,應該去問問自己為什么要用這個東西,AFNetworking3.x是基于NSURLSession來封裝的, 現(xiàn)在來總結一下NSURLSession的用法
Xcode 7+ is required.NSURLConnectionOperation support has been removed

解決這個疑惑, 請你拜讀以下的文章
NSURLSession 入門教程
別說你會AFNetworking3.0/NSURLSession
忘記NSURLConnection,擁抱NSURLSession吧!

1. NSURLSession是什么?##

先來看兩個圖

NSURLSession及其組成類

NSURLSession類中提供三個類方法創(chuàng)建URLSession對象
  1. NSURLSession負責發(fā)送和接收HTTP的請求。
  2. NSURLSession由NSURLSessionConfiguration(我理解為一份配置)和NSURLSessionDelegate & NSOperationQueue(一份協(xié)議)組成
    每一個NSURLSession對象都是根據(jù)一個NSURLSessionConfiguration初始化的,該NSURLSessionConfiguration指定了上面提到的政策,以及一系列為了提高移動設備性能而專門添加的新選項。
    而NSURLSession的另一重要組成部分是會話任務,它負責處理數(shù)據(jù)的加載,以及客戶端與服務器之間的文件和數(shù)據(jù)的上傳下載服務。NSURLSessionTask與NSURLConnection是及其相似的,因為它負責加載數(shù)據(jù),而主要的區(qū)別在于,任務共享它們父類NSURLSession的共同委托(common delegate)。

/*
 * The shared session uses the currently set global NSURLCache,
 * NSHTTPCookieStorage and NSURLCredentialStorage objects.
 */
// 創(chuàng)建默認NSURLSession對象 默認使用defaultSessionConfiguration
// 使用的是全局的cache,cookie和credential storage objects來創(chuàng)建configuration對象
// 通過默認配置來創(chuàng)建一個NSURLSession并且不需要協(xié)議
+ (NSURLSession *)sharedSession;

/*
 * Customization of NSURLSession occurs during creation of a new session.
 * If you only need to use the convenience routines with custom
 * configuration options it is not necessary to specify a delegate.
 * If you do specify a delegate, the delegate will be retained until after
 * the delegate has been sent the URLSession:didBecomeInvalidWithError: message.
 */
/*
// 通過一份連接配置來創(chuàng)建一個NSURLSession
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;

// 通過一份連接配置和一份協(xié)議來創(chuàng)建一個NSURLSession
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;

2. NSURLSessionConfiguration是什么?##

我理解為一份配置, 而這份配置就是儲存這個整個連接的一些基本屬性例如 : 會話屬性,如超時值,高速緩存的政策和額外的HTTP標頭等

NSURLSessionConfiguration類

三種創(chuàng)建方式 :

//  創(chuàng)建一個使用磁盤堅持全局緩存,證書和cookie的默認配置對象。
+ (NSURLSessionConfiguration *)defaultSessionConfiguration;

// 類似于默認配置,用于“private” sessions,對于cache, cookie, or credential storage objects的非永久存儲。
+ (NSURLSessionConfiguration *)ephemeralSessionConfiguration;

// 讓會話在后臺執(zhí)行上傳或下載任務。當應用程序本身被暫?;蚪K止轉讓甚至繼續(xù)。iOS 8.0后提供的屬性
// 做遠程push通知或是應用程序掛起的時候就要用到這個configuration
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier NS_AVAILABLE(10_10, 8_0); 

常規(guī)配置屬性 :

/* 常規(guī)屬性 - 常規(guī)屬性有7個  */ 
/*background 模式下需要標識 */
@property (nullable, readonly, copy) NSString *identifier;

/*超時屬性 ,用作設置timeoutIntervalForRequest時間內, 如果沒有請求數(shù)據(jù)發(fā)送,則請求超時 */
@property NSTimeInterval timeoutIntervalForRequest;

/* 超時屬性, 用作設置timeoutIntervalForResource時間內,如果沒有返回響應,則響應超時 */
@property NSTimeInterval timeoutIntervalForResource;

/* 網(wǎng)絡服務類型 */
typedef NS_ENUM(NSUInteger, NSURLRequestNetworkServiceType)
{
    NSURLNetworkServiceTypeDefault = 0, // Standard internet traffic
    NSURLNetworkServiceTypeVoIP = 1, // Voice over IP control traffic  
    NSURLNetworkServiceTypeVideo = 2, // Video traffic
    NSURLNetworkServiceTypeBackground = 3, // Background traffic
    NSURLNetworkServiceTypeVoice = 4    // Voice data
};
// 這個屬性一般用于音頻處理流
@property NSURLRequestNetworkServiceType networkServiceType;

// 設置這個屬性, 會為所有的NSURLSessionTask加上基礎request頭,可以統(tǒng)一請求頭
@property (nullable, copy) NSDictionary *HTTPAdditionalHeaders;

// 一個布爾值,確定是否通過蜂窩網(wǎng)絡連接, 默認為YES , 
@property BOOL allowsCellularAccess;

// iOS8.0后才能用, backgroundSessionConfigurationWithIdentifier中的identifier中對應使用, 被標識的文件,會在后臺中下載
@property (nullable, copy) NSString *sharedContainerIdentifier NS_AVAILABLE(10_10, 8_0);

cookie策略配置

// NSHTTPCookieAcceptPolicy, 配置處理cookie的策略, 
typedef NS_ENUM(NSUInteger, NSHTTPCookieAcceptPolicy) {
    NSHTTPCookieAcceptPolicyAlways, // 總是接受cookie
    NSHTTPCookieAcceptPolicyNever, // 總是不接受cookie
    NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain // 只從DocumentDomain文件中接受緩存
};
@property NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy

// HTTPCookieStorage類, 提供了一些方法, 這個類的作用是儲存請求的cookie, 待下一次請求的時候, 會再次將上次保存下來了的cookie繼續(xù)去請求
@property(retain) NSHTTPCookieStorage *HTTPCookieStorage

// 一個布爾值,確定是否請求應包含來自cookie存儲的cookie。The default value is YES
@property BOOL HTTPShouldSetCookies

安全策略配置

// TLSMaximumSupportedProtocol 和 TLSMinimumSupportedProtocol 確定是否支持SSLProtocol版本的會話。

/* The minimum allowable versions of the TLS protocol, from <Security/SecureTransport.h> SSL協(xié)議*/
@property SSLProtocol TLSMinimumSupportedProtocol;

/* The maximum allowable versions of the TLS protocol, from <Security/SecureTransport.h> SSL協(xié)議*/
@property SSLProtocol TLSMaximumSupportedProtocol;

// NSURLCredentialStorage類管理的是task會話中使用任務憑據(jù)存儲對象。
@property(retain) NSURLCredentialStorage *URLCredentialStorage

緩存策略配置

// NSURLRequestCachePolicy枚舉
typedef NS_ENUM(NSUInteger, NSURLRequestCachePolicy)
{
// 默認的緩存策略, 如果緩存不存在,直接從服務端獲取。如果緩存存在,會根據(jù)response中的Cache-Control字段判斷下一步操作,如: Cache-Control字段為must-revalidata, 則詢問服務端該數(shù)據(jù)是否有更新,無更新的話直接返回給用戶緩存數(shù)據(jù),若已更新,則請求服務端.
    NSURLRequestUseProtocolCachePolicy = 0, 
// 忽略本地緩存數(shù)據(jù),直接請求服務端.
    NSURLRequestReloadIgnoringLocalCacheData = 1,
// Unimplemented 未實現(xiàn)枚舉值
    NSURLRequestReloadIgnoringLocalAndRemoteCacheData = 4, // Unimplemented
// 相當于NSURLRequestReloadIgnoringLocalCacheData, 忽略本地緩存數(shù)據(jù),直接請求服務端.
    NSURLRequestReloadIgnoringCacheData = NSURLRequestReloadIgnoringLocalCacheData,
// 有緩存就使用,不管其有效性(即忽略Cache-Control字段), 無則請求服務端.
    NSURLRequestReturnCacheDataElseLoad = 2,
// 加載本地緩存. 有就加載, 沒有就當加載失敗處理. (確定當前無網(wǎng)絡時使用)
    NSURLRequestReturnCacheDataDontLoad = 3,
// Unimplemented 未實現(xiàn)枚舉值
    NSURLRequestReloadRevalidatingCacheData = 5, // Unimplemented
};
/* 請求的默認緩存策略 ,有以上幾種方式*/
// 指定了一個請求的緩存響應的方式,和應該在什么時候返回
@property NSURLRequestCachePolicy requestCachePolicy;

/* The URL resource cache, or nil to indicate that no caching is to be performed */
// 是會話使用的緩存。默認情況下,NSURLCache 的+ sharedURLCache 會被使用
@property (nullable, retain) NSURLCache *URLCache;

設置HTTP策略和代理屬性

/* The proxy dictionary, as described by <CFNetwork/CFHTTPStream.h> */
// 指定了Session(會話)連接中的代理服務器。同樣地,大多數(shù)面向消費者的應用程序都不需要代理,所以基本上不需要配置這個屬性。
@property (nullable, copy) NSDictionary *connectionProxyDictionary;

/* The maximum number of simultanous persistent connections per host */
// 是 Foundation 框架中URL加載系統(tǒng)的一個新的配置選項。它曾經(jīng)被用于NSURLConnection管理私人連接池。現(xiàn)在有了NSURLSession,開發(fā)者可以在需要時限制連接到特定主機的數(shù)量。
@property NSInteger HTTPMaximumConnectionsPerHost;

/* Allow the use of HTTP pipelining */
// 也出現(xiàn)在NSMutableURLRequest,它可以被用于開啟HTTP管道,這可以顯著降低請求的加載時間,但是由于沒有被服務器廣泛支持,默認是禁用的。
@property BOOL HTTPShouldUsePipelining;

3. NSURLSessionTask是什么?##

NSURLSessionTask是一個抽象子類,它有三個具體的子類是可以直接使用的:NSURLSessionDataTask,NSURLSessionUploadTask和NSURLSessionDownloadTask。這三個類封裝了現(xiàn)代應用程序的三個基本網(wǎng)絡任務:獲取數(shù)據(jù),比如JSON或XML,以及上傳下載文件。

Paste_Image.png

NSURLSessionTask的三個子類completionHandler處理方式有點不同
NSURLSessionDataTask (JSON或XML) :
數(shù)據(jù)在完成時立即返回,

NSURLSessionDownloadTask(下載文件) :
下載任務將數(shù)據(jù)寫入本地的臨時文件。completionHandler將文件從它的臨時位置移動到一個永久位置,這個永久位置就是塊的返回值。它會帶回已下載文件的一個臨時的文件路徑location.

NSURLSessionUploadTask(上傳文件)
因為一般來說,服務端對于一個上傳任務的響應也會有相關數(shù)據(jù)返回,所以NSURLSessionUploadTask


3.1 已經(jīng)有了NSURLSessionDataTask, 為什么還有繼承多一層NSURLSessionUploadTask??###

從兩者提供的對應task 生成的方法能看。比如使用dataTask來進行上傳任務的時候,需要指定HTTPMethod為POST或PUT,并且提供的數(shù)據(jù)(NSData)得賦值給request.HTTPBody。而使用uploadTask來進行上傳任務的時候,只需要使用- uploadTaskWithRequest:fromData:或- uploadTaskWithRequest:fromFile:之類的方法,其中參數(shù)的話只需要根提供數(shù)據(jù)(NSData)或者數(shù)據(jù)的磁盤位置(NSURL*fileURL)就可以構造出一個上傳的session task了,簡化了操作。


NSURLSessionTask 的屬性

// 任務標識,唯一確定一個任務
@property (readonly)                 NSUInteger    taskIdentifier;    /* an identifier for this task, assigned by and unique to the owning session */
// 上一個請求對象
@property (nullable, readonly, copy) NSURLRequest  *originalRequest;  /* may be nil if this is a stream task */
// 當前請求對象
@property (nullable, readonly, copy) NSURLRequest  *currentRequest;   /* may differ from originalRequest due to http server redirection */
// 服務器的響應數(shù)據(jù)
@property (nullable, readonly, copy) NSURLResponse *response;         /* may be nil if no response has been received */

/* 如果不存在響應實體, 字節(jié)數(shù)可以為零 
 * or NSURLSessionTransferSizeUnknown if it is not possible 
 * to know how many bytes will be transferred.
 */

/* number of body bytes already received */
// 已經(jīng)接收到的數(shù)據(jù)量
@property (readonly) int64_t countOfBytesReceived;

/* number of body bytes already sent */
// 已經(jīng)發(fā)送的數(shù)據(jù)量
@property (readonly) int64_t countOfBytesSent;

/* number of body bytes we expect to send, derived from the Content-Length of the HTTP request */
// 所要發(fā)送的總數(shù)據(jù)量
@property (readonly) int64_t countOfBytesExpectedToSend;

/* number of byte bytes we expect to receive, usually derived from the Content-Length header of an HTTP response. */
// 所要接收到的總數(shù)據(jù)量
@property (readonly) int64_t countOfBytesExpectedToReceive;

/*
 * The taskDescription property is available for the developer to
 * provide a descriptive label for the task.
 */
// 任務描述.不知道用處在什么地方
@property (nullable, copy) NSString *taskDescription;

/* -cancel returns immediately, but marks a task as being canceled.
 * The task will signal -URLSession:task:didCompleteWithError: with an
 * error value of { NSURLErrorDomain, NSURLErrorCancelled }.  In some 
 * cases, the task may signal other work before it acknowledges the 
 * cancelation.  -cancel may be sent to a task that has been suspended.
 */
// 取消任務 
- (void)cancel;

/*
 * Suspending a task will prevent the NSURLSession from continuing to
 * load data.  There may still be delegate calls made on behalf of
 * this task (for instance, to report data received while suspending)
 * but no further transmissions will be made on behalf of the task
 * until -resume is sent.  The timeout timer associated with the task
 * will be disabled while a task is suspended. -suspend and -resume are
 * nestable. 
 */
// 暫停任務
- (void)suspend;

// 繼續(xù)任務 / 開始任務
- (void)resume;

/*
 * The current state of the task within the session.
 */
// 會話狀態(tài),NSURLSessionTaskState 枚舉 有4個狀態(tài)
@property (readonly) NSURLSessionTaskState state;

/*
 * The error, if any, delivered via -URLSession:task:didCompleteWithError:
 * This property will be nil in the event that no error occured.
 */
// 錯誤信息 通過-URLSession:task:didCompleteWithError:來傳遞
@property (nullable, readonly, copy) NSError *error;


NSURLSessionDataTask 與 NSURLSessionUploadTask都沒有擴展方法和屬性
NSURLSessionDownloadTask 擴展了一個方法

// 提供了一個取消任務的方法,而且會保存用于以后繼續(xù)任務的信息,方法如下:
- (void)cancelByProducingResumeData:(void (^)(NSData * __nullable resumeData))completionHandler;

總結一下 !##

與NSURLConnection類似,除了同名類NSURLSession,NSURLSession也是指一組相互依賴的類。NSURLSession包括與之前相同的組件,例如NSURLRequest, NSURLCache等。NSURLSession的不同之處在于,它把 NSURLConnection替換為NSURLSession, NSURLSessionConfiguration,以及3個NSURLSessionTask的子類NSURLSessionDataTask, NSURLSessionUploadTask, 和NSURLSessionDownloadTask, IOS9之后又多了一個NSURLSessionStreamTask
NSURLSession最直接的改善就是提供了配置每個會話的緩存,協(xié)議,cookie和證書政策(credential policies),甚至跨應用程序共享它們的能力. 一種很好的設計思想, 將網(wǎng)絡基礎架構和部分應用程序獨立工作,互相不會干擾.

一個NSURLSession(會話), 是通過一份NSURLSessionConfiguration(對于會話如何產生請求,提供了相當多的控制和靈活性。從網(wǎng)絡訪問性能,到cookie,安全性,緩存策略,自定義協(xié)議,啟動事件設置,以及用于移動設備優(yōu)化的幾個新屬性)從而初始化一個NSURLSession(會話), 當然同時也可以遵守一些Delegate協(xié)議,從而擴展一些方法

定義NSURLSessionConfiguration(配置) - > (可選)遵守協(xié)議(NSURLSessionDelegate) ->創(chuàng)建NSURLSession(會話) ->根據(jù)實質需求定義NSURLSessionTask(任務)

后記 : 寫文章的過程中,是對自己的思維的一個總結,翻查了很多文檔,同時也交叉對比了一些文檔與文章中的話,只有理解了基礎, 才可以玩得很6, 下一章我將會開始扣AFNetworking 3.0+框架中,是怎樣設計這些類的使用的.

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯(lián)系作者
【社區(qū)內容提示】社區(qū)部分內容疑似由AI輔助生成,瀏覽時請結合常識與多方信息審慎甄別。
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發(fā)布,文章內容僅代表作者本人觀點,簡書系信息發(fā)布平臺,僅提供信息存儲服務。

相關閱讀更多精彩內容

友情鏈接更多精彩內容