NSURLConnection主要API如下
/*
創(chuàng)建一個NSURLConnection,只建立連接,并沒有下載數(shù)據(jù)
request: 請求內(nèi)容
delegate:NSURLConnectionDelegate,NSURLConnection實(shí)例會強(qiáng)引用delegate,直到回調(diào)didFinishLoading,didFailWithErrorNSURLConnection.cancel調(diào)用
startImmediately : 是否立即下載數(shù)據(jù),YES立即下載,自動把connection加入到當(dāng)前的主線程runloop中,且任務(wù)完成的結(jié)果會在主線程的runloop中回調(diào)。NO,只建立連接,不下載數(shù)據(jù),需要手動把connection加入到指定的runloop中。需要手動【connection start】開始下載數(shù)據(jù)。
*/
- (nullable instancetype)initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate startImmediately:(BOOL)startImmediately API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.5,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
/*
其實(shí)就是用的[self initWithRequest:request delegate:delegate startImmediately:YES];不需要顯示的在去調(diào)用【connection start】
*/
- (nullable instancetype)initWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
/*
其實(shí)就是用的[self initWithRequest:request delegate:delegate startImmediately:YES];不需要顯示的在去調(diào)用【connection start】
*/
+ (nullable NSURLConnection*)connectionWithRequest:(NSURLRequest *)request delegate:(nullable id)delegate API_DEPRECATED("Use NSURLSession (see NSURLSession.h)", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
/*
建立連接時用的請求
*/
@property (readonly, copy) NSURLRequest *originalRequest API_AVAILABLE(macos(10.8), ios(5.0), watchos(2.0), tvos(9.0));
/*
建立連接的請求進(jìn)過認(rèn)證協(xié)議可能會改變
*/
@property (readonly, copy) NSURLRequest *currentRequest API_AVAILABLE(macos(10.8), ios(5.0), watchos(2.0), tvos(9.0));
/*
開始下載數(shù)據(jù),通過- (instancetype)initWithRequest:(NSURLRequest
*)request delegate:(id)delegate startImmediately:(BOOL)startImmediately
初始化的實(shí)例,調(diào)用【connection start】
*/
- (void)start API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
/*
斷開網(wǎng)絡(luò)連接,取消請求,cancel方法不能保證代理回調(diào)立即不會調(diào)用(應(yīng)該是請求到的數(shù)據(jù),只能傳給代理),cancel會release delegate
*/
- (void)cancel;
/*
將connection實(shí)例回調(diào)加入到一個runloop,NSURLConnectionDelegate回調(diào)會在這個runloop中響應(yīng)注意該方法不能跟setDelegateQueue同時設(shè)置,只能選擇一個。
*/
- (void)scheduleInRunLoop:(NSRunLoop *)aRunLoop forMode:(NSRunLoopMode)mode API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
/*
取消在這個runloop中的回調(diào)
*/
- (void)unscheduleFromRunLoop:(NSRunLoop *)aRunLoop forMode:(NSRunLoopMode)mode API_AVAILABLE(macos(10.5), ios(2.0), watchos(2.0), tvos(9.0));
/*
如果設(shè)置了queue,回調(diào)將會在這個queue上進(jìn)行,回調(diào)一次就生成了一個NSBlockOperation加入到了queue中注意該方法不能跟scheduleInRunLoop同時設(shè)置,只能選擇一個。
*/
- (void)setDelegateQueue:(nullable NSOperationQueue*) queue API_AVAILABLE(macos(10.7), ios(5.0), watchos(2.0), tvos(9.0));
/*
類方法創(chuàng)建一個同步請求。這個方法是建立在異步的基礎(chǔ)上,然后阻塞當(dāng)前線程實(shí)現(xiàn)的
response:響應(yīng)頭信息,傳遞一個二維指針
error:請求結(jié)果的狀態(tài)
*/
+ (nullable NSData *)sendSynchronousRequest:(NSURLRequest *)request returningResponse:(NSURLResponse * _Nullable * _Nullable)response error:(NSError **)error API_DEPRECATED("Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h", macos(10.3,10.11), ios(2.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
/*
發(fā)起一個異步請求
queue:completionHandler會運(yùn)行在這個queue中
completionHandler:請求回調(diào)block
*/
+ (void)sendAsynchronousRequest:(NSURLRequest*) request
queue:(NSOperationQueue*) queue
completionHandler:(void (^)(NSURLResponse* _Nullable response, NSData* _Nullable data, NSError* _Nullable connectionError)) handler API_DEPRECATED("Use [NSURLSession dataTaskWithRequest:completionHandler:] (see NSURLSession.h", macos(10.7,10.11), ios(5.0,9.0), tvos(9.0,9.0)) __WATCHOS_PROHIBITED;
NSURLSession主要API如下(所有創(chuàng)建task的方法,只要帶有completionHandler這個參數(shù)的,均表示為請求過程中不會觸發(fā)代理方法。所有不帶有completionHandler這個參數(shù)的,均會走代理方法流程。如果你實(shí)現(xiàn)了URLSession:didReceiveChallenge:completionHandler:方法又沒有在該方法調(diào)用completionHandler,請求就會遭到阻塞。)
/*
直接創(chuàng)建,使用當(dāng)前設(shè)置的全局NSURLCache,
NSHTTPCookieStorage和NSURLCredentialStorage對象。
*/
@property (class, readonly, strong) NSURLSession *sharedSession;
/*
第一個粒度較低就是根據(jù)剛才創(chuàng)建的Configuration創(chuàng)建一個Session,系統(tǒng)默認(rèn)創(chuàng)建一個新的OperationQueue處理Session的消息。自定義配置文件, 設(shè)置代理, 大部分時間我們都是用這個
*/
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration;
/*
第二個粒度比較高,可以設(shè)定回調(diào)的delegate(注意這個回調(diào)delegate會被強(qiáng)引用),并且可以設(shè)定delegate在哪個OperationQueue回調(diào),如果我們將其設(shè)置為[NSOperationQueue mainQueue]就能在主線程進(jìn)行回調(diào)非常的方便。
*/
+ (NSURLSession *)sessionWithConfiguration:(NSURLSessionConfiguration *)configuration delegate:(nullable id <NSURLSessionDelegate>)delegate delegateQueue:(nullable NSOperationQueue *)queue;
@property (readonly, retain) NSOperationQueue *delegateQueue;
@property (nullable, readonly, retain) id <NSURLSessionDelegate> delegate;
@property (readonly, copy) NSURLSessionConfiguration *configuration;
@property (nullable, copy) NSString *sessionDescription;
/*
調(diào)用finishTasksAndInvalidate方法讓任務(wù)繼續(xù)運(yùn)行,在運(yùn)行結(jié)束時取消session。
不再需要session的時候調(diào)用invalidateAndCancel方法停止所有任務(wù)并使session失效。
session失效之后會給URLSession:didBecomeInvalideWithError:方法發(fā)送消息,當(dāng)這個方法返回之后,session不再對delegate持有強(qiáng)引用。
*/
- (void)finishTasksAndInvalidate;
- (void)invalidateAndCancel;
/*
NSURLSession設(shè)置過代理后,需要在最后(比如控制器銷毀的時候)調(diào)用session的invalidateAndCancel或者resetWithCompletionHandler,才不會有內(nèi)存泄露。清空cookies, 緩存和證書存儲, 移除所有磁盤文件, 清理正在執(zhí)行的下載任務(wù), 確保未來能響應(yīng)一個新的socket請求
*/
- (void)resetWithCompletionHandler:(void (^)(void))completionHandler;
/*
清除硬盤上的cookies和證書, 清理暫時的緩存, 確保未來能響應(yīng)一個新的TCP請求
*/
- (void)flushWithCompletionHandler:(void (^)(void))completionHandler;
/*
異步調(diào)用session中所有upload, download, data tasks的completion回調(diào).
*/
- (void)getTasksWithCompletionHandler:(void (^)(NSArray<NSURLSessionDataTask *> *dataTasks, NSArray<NSURLSessionUploadTask *> *uploadTasks, NSArray<NSURLSessionDownloadTask *> *downloadTasks))completionHandler;
- (void)getAllTasksWithCompletionHandler:(void (^)(NSArray<__kindof NSURLSessionTask *> *tasks))completionHandler API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0));
/*
創(chuàng)建NSURLSessionDataTask
*/
- (NSURLSessionDataTask *)dataTaskWithRequest:(NSURLRequest *)request;
- (NSURLSessionDataTask *)dataTaskWithURL:(NSURL *)url;
/*
創(chuàng)建NSURLSessionUploadTask
*/
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromFile:(NSURL *)fileURL;
- (NSURLSessionUploadTask *)uploadTaskWithRequest:(NSURLRequest *)request fromData:(NSData *)bodyData;
- (NSURLSessionUploadTask *)uploadTaskWithStreamedRequest:(NSURLRequest *)request;
/*
創(chuàng)建NSURLSessionDownloadTask
*/
- (NSURLSessionDownloadTask *)downloadTaskWithRequest:(NSURLRequest *)request;
- (NSURLSessionDownloadTask *)downloadTaskWithURL:(NSURL *)url;
- (NSURLSessionDownloadTask *)downloadTaskWithResumeData:(NSData *)resumeData;
/*
通過一個指定的IP地址, 端口號來創(chuàng)建一個NSURLSessionStreamTask
*/
- (NSURLSessionStreamTask *)streamTaskWithHostName:(NSString *)hostname port:(NSInteger)port API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;
/*
通過一個指定的NSNetService對象來創(chuàng)建NSURLSessionStreamTask
*/
- (NSURLSessionStreamTask *)streamTaskWithNetService:(NSNetService *)service API_AVAILABLE(macos(10.11), ios(9.0), tvos(9.0)) __WATCHOS_PROHIBITED;
NSURLSessionConfiguration主要API如下
/*
內(nèi)置的配置對象
通過類方法,NSURLSessionConfiguration提供了適用于不同情況的配置對象,它們的一些配置屬性設(shè)置了不同的默認(rèn)值。
+ defaultSessionConfiguration,默認(rèn)的配置對象,持久化存儲緩存,證書,cookie。
+ ephemeralSessionConfiguration,不持久化存儲緩存,證書,cookie的配置。所有相關(guān)內(nèi)容只保存在內(nèi)存中,當(dāng) session 失效或應(yīng)用終止,所有內(nèi)容被清空。該配置可提高私密性,因?yàn)椴粫蛴脖P上寫入數(shù)據(jù)。
+ backgroundSessionConfigurationWithIdentifier:,適用于在后臺上傳和下載文件的網(wǎng)絡(luò)請求。當(dāng)應(yīng)用被系統(tǒng)終止并重啟,傳入的參數(shù) identifier 可用來重新創(chuàng)建配置和 session 對象,以便恢復(fù)中斷的下載任務(wù)。如果是用戶主動終止程序,則不會有上述行為。
*/
/*
一般模式(default):工作模式類似于原來的NSURLConnection,可以使用緩存的Cache,Cookie,鑒權(quán)。
*/
@property (class, readonly, strong) NSURLSessionConfiguration *defaultSessionConfiguration;
/*
及時模式(ephemeral):不使用緩存的Cache,Cookie,鑒權(quán)。 僅內(nèi)存緩存, 不做磁盤緩存的配置
*/
@property (class, readonly, strong) NSURLSessionConfiguration *ephemeralSessionConfiguration;
/*
后臺模式(background):在后臺完成上傳下載,創(chuàng)建Configuration對象的時候需要給一個NSString的ID用于追蹤完成工作的Session是哪一個(后面會講到)。
*/
+ (NSURLSessionConfiguration *)backgroundSessionConfigurationWithIdentifier:(NSString *)identifier API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
/*
普通配置項(xiàng)
identifier,用于唯一標(biāo)識一個后臺下載的 session,當(dāng)系統(tǒng)重啟被自動關(guān)閉的應(yīng)用時,可以通過這個標(biāo)識符,重新創(chuàng)建 configuration 和 session 對象來恢復(fù)中斷的下載。
HTTPAdditionalHeaders,一個 dictionary,包含了需要額外添加到 session 中所有 request 的 header,如User-Agent。不應(yīng)添加
Authorization、Connection、Host和WWW-Authenticate。如果 request 中已存在某一 header,則使用 request 中的值,該 dictionary 默認(rèn)為空。
networkServiceType,NSURLRequestNetworkServiceType類型,network service type 影響著操作系統(tǒng)對于網(wǎng)絡(luò)傳輸?shù)膬?yōu)先級排列,進(jìn)而影響系統(tǒng)電量、性能的消耗。默認(rèn)值是NSURLNetworkServiceTypeDefault。
allowsCellularAccess,布爾值,指明在移動網(wǎng)絡(luò)下是否可發(fā)起請求。
timeoutIntervalForRequest,請求的超時時間,默認(rèn)值為60秒。
timeoutIntervalForResource,所有資源下載或上傳完成的超時時間,中間請求失敗可重新請求,單位為秒,默認(rèn)時間為7天。
sharedContainerIdentifier,用于應(yīng)用擴(kuò)展與應(yīng)用間的后臺會話的擴(kuò)展容器。
*/
@property (nullable, readonly, copy) NSString *identifier;
@property (nullable, copy) NSDictionary *HTTPAdditionalHeaders;
@property NSURLRequestNetworkServiceType networkServiceType;
@property BOOL allowsCellularAccess;
@property NSTimeInterval timeoutIntervalForRequest;
@property NSTimeInterval timeoutIntervalForResource;
@property (nullable, copy) NSString *sharedContainerIdentifier API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
/*
后臺下載配置項(xiàng)
sessionSendsLaunchEvents,布爾值,說明在 session task 完成或者需要驗(yàn)證時,是否在后臺運(yùn)行應(yīng)用。當(dāng)設(shè)為 YES 時,系統(tǒng)會自動啟動或運(yùn)行應(yīng)用,并調(diào)用 AppDelegate 中的方法
application:handleEventsForBackgroundURLSession:completionHandler:,通過參數(shù)提供上述提到的唯一標(biāo)識后臺下載 session 的 identifier。
discretionary,布爾值,說明在下載時是否由系統(tǒng)統(tǒng)一安排資源。
*/
@property BOOL sessionSendsLaunchEvents API_AVAILABLE(ios(7.0), watchos(2.0), tvos(9.0)) API_UNAVAILABLE(macos);
@property (getter=isDiscretionary) BOOL discretionary API_AVAILABLE(macos(10.10), ios(7.0), watchos(2.0), tvos(9.0));
/*
安全相關(guān)配置項(xiàng)
TLSMaximumSupportedProtocol,SSLProtocol 類型,請求支持的最高 TLS 版本,默認(rèn)值是 kTLSProtocol12,即 TLS1.2。
TLSMinimumSupportedProtocol,SSLProtocol 類型,請求支持的最低 TLS 版本,默認(rèn)值是 kSSLProtocol3,即 SSL3.0。
URLCredentialStorage,管理需要驗(yàn)證的請求證書。
*/
@property SSLProtocol TLSMinimumSupportedProtocol;
@property SSLProtocol TLSMaximumSupportedProtocol;
@property (nullable, retain) NSURLCredentialStorage *URLCredentialStorage;
/*
HTTP相關(guān)配置項(xiàng)
HTTPMaximumConnectionsPerHost,session 內(nèi)一個域名的最大同時連接數(shù)。
HTTPShouldUsePipelining,布爾值,說明 session 內(nèi)的 task 是否使用 HTTP pipelining。
connectionProxyDictionary,字典類型,保存了連接代理的相關(guān)信息,默認(rèn)為 NULL。
*/
@property NSInteger HTTPMaximumConnectionsPerHost;
@property BOOL HTTPShouldUsePipelining;
@property (nullable, copy) NSDictionary *connectionProxyDictionary;
/*
HTTP cookie 相關(guān)配置項(xiàng)
HTTPCookieAcceptPolicy,接收 cookie 的策略,
NSHTTPCookieAcceptPolicy類型,默認(rèn)值是
NSHTTPCookieAcceptPolicyOnlyFromMainDocumentDomain
HTTPCookieStorage,對于default 和 background session,該屬性值為NSHTTPCookieStorage的單例對象,而 ephemeral session 的默認(rèn)值為一個私有的NSHTTPCookieStorage對象,只將 cookie 保存在內(nèi)存中,如果 session 不想保存 cookie,可將該屬性設(shè)為 nil。
HTTPShouldSetCookies,布爾值,指明請求時是否攜帶 cookie 信息。
*/
@property NSHTTPCookieAcceptPolicy HTTPCookieAcceptPolicy;
@property (nullable, retain) NSHTTPCookieStorage *HTTPCookieStorage;
@property BOOL HTTPShouldSetCookies;
/*
緩存策略配置項(xiàng)
`URLCache`,用于保存緩存響應(yīng)的[NSURLCache]對象,default session 默認(rèn)使用`NSURLCache`的單例對象,background session 的默認(rèn)值為 nil,而 ephemeral session 的默認(rèn)值是一個私有的`NSURLCache`對象,數(shù)據(jù)只保存在內(nèi)存中。如果不想使用緩存,可直接設(shè)置該值為 nil。
`requestCachePolicy`,枚舉類型`NSURLRequestCachePolicy`,指明了請求使用緩存響應(yīng)的策略。
// 默認(rèn)值,使用協(xié)議本身的緩存邏輯。
NSURLRequestUseProtocolCachePolicy
// 不使用現(xiàn)有緩存,數(shù)據(jù)需要從原始地址加載。
NSURLRequestReloadIgnoringLocalCacheData
// 無論緩存是否過期,先使用本地緩存數(shù)據(jù)。如果緩存中沒有請求所對應(yīng)的數(shù)據(jù),那么從原始地址加載數(shù)據(jù)。
NSURLRequestReturnCacheDataElseLoad
// 無論緩存是否過期,先使用本地緩存數(shù)據(jù)。如果緩存中沒有請求所對應(yīng)的數(shù)據(jù),那么放棄從原始地址加載數(shù)據(jù),請求視為失敗。
NSURLRequestReturnCacheDataDontLoad
*/
@property (nullable, retain) NSURLCache *URLCache;
@property NSURLRequestCachePolicy requestCachePolicy;
/*
自定義協(xié)議配置項(xiàng)
protocolClasses,由自定義實(shí)現(xiàn)的NSURLProtocol子類的 Class 對象組成的數(shù)組,配置了 session 支持的自定義協(xié)議。
*/
@property (nullable, copy) NSArray<Class> *protocolClasses;
/*
iOS11新增加API。一個更加靈活的網(wǎng)絡(luò)請求API,它能夠等待直到你的手機(jī)連接上了安全的網(wǎng)絡(luò),如果是不安全的網(wǎng)絡(luò)則該網(wǎng)絡(luò)請求不會調(diào)用。
*/
@property BOOL waitsForConnectivity API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
/*
MutliPath TCP
Multipath protocols for Multipath Devices(適合多鏈路設(shè)備的多鏈路 TC P協(xié)議)增加了對使用多個接口(如Wi-Fi和Cellular)的支持
通過擴(kuò)展 URLSessionConfiguration 以支持 IETF、RFC 6824中定義的多路徑TCP傳輸單個數(shù)據(jù)流。有關(guān)更多信息,請參閱URLSessionConfiguration.MultipathServiceType。
*/
@property NSURLSessionMultipathServiceType multipathServiceType API_AVAILABLE(ios(11.0)) API_UNAVAILABLE(macos, watchos, tvos);
/*
為創(chuàng)建的任何tcp套接字啟用擴(kuò)展后臺空閑模式。 啟用此模式會要求系統(tǒng)保持打開狀態(tài),并在進(jìn)程移動到后臺時延遲回收
*/
@property BOOL shouldUseExtendedBackgroundIdleMode API_AVAILABLE(macos(10.11), ios(9.0), watchos(2.0), tvos(9.0));
NSURLSessionTask主要API如下
/*
相關(guān)信息
originalRequest,創(chuàng)建 task 時對應(yīng)的請求對象。
currentRequest,當(dāng)響應(yīng)為重定向到其他 URL 時,該值會改變。
response,服務(wù)端返回的NSURLResponse對象。
taskIdentifier,NSUInteger類型,task 在 session 內(nèi)的唯一標(biāo)識。
error,當(dāng)任務(wù)失敗時的NSError對象。
taskDescription,可給任務(wù)設(shè)置一個可讀的描述,在如果需要界面展示時使用。
*/
@property (nullable, readonly, copy) NSURLRequest *originalRequest;
@property (nullable, readonly, copy) NSURLRequest *currentRequest;
@property (nullable, readonly, copy) NSURLResponse *response;
@property (readonly) NSUInteger taskIdentifier;
@property (nullable, copy) NSString *taskDescription;
@property (readonly, strong) NSProgress *progress API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
@property (nullable, copy) NSDate *earliestBeginDate API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
@property int64_t countOfBytesClientExpectsToSend API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
@property int64_t countOfBytesClientExpectsToReceive API_AVAILABLE(macos(10.13), ios(11.0), watchos(4.0), tvos(11.0));
/*
進(jìn)度信息
countOfBytesExpectedToSend,請求體的字節(jié)數(shù),系統(tǒng)根據(jù) header 中的 Content-Length 字段,或者作為請求體的NSData或文件的大小來設(shè)置該值。
countOfBytesSent,已發(fā)送的請求體字節(jié)數(shù),當(dāng)該值變化,會觸發(fā)代理方法
-URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:
countOfBytesExpectedToReceive,響應(yīng)體期望收到的字節(jié)數(shù),根據(jù)響應(yīng) header 中的 Content-Length 字段,若未指明,則該值為
NSURLSessionTransferSizeUnknown(-1)
countOfBytesReceived,已收到的響應(yīng)體字節(jié)數(shù),當(dāng)該值變化,會觸發(fā)代理方法- URLSession:dataTask:didReceiveData:或
URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:
*/
@property (readonly) int64_t countOfBytesReceived;
@property (readonly) int64_t countOfBytesSent;
@property (readonly) int64_t countOfBytesExpectedToSend;
@property (readonly) int64_t countOfBytesExpectedToReceive;
- (void)cancel;
/*
控制 task 的狀態(tài)
task 的當(dāng)前狀態(tài)由枚舉類型NSURLSessionTaskState的屬性 state 表示,包含以下幾種可能的值:
typedef NS_ENUM(NSInteger, NSURLSessionTaskState) {
NSURLSessionTaskStateRunning = 0,
NSURLSessionTaskStateSuspended = 1,
NSURLSessionTaskStateCanceling = 2, /*當(dāng)向task發(fā)送cancel消息后,會轉(zhuǎn)變?yōu)樵摖顟B(tài),代理會收到- URLSession:task:didCompleteWithError:消息*/
NSURLSessionTaskStateCompleted = 3, /*完成狀態(tài)不包括被取消的情況*/
};
通過NSURLSession 創(chuàng)建的 task 默認(rèn)是狀態(tài)是 suspended,調(diào)用- resume 方法后,task 的狀態(tài)變?yōu)?running。通過- suspend 方法可以將 task 重新變?yōu)閽炱馉顟B(tài),當(dāng)恢復(fù) running 狀態(tài)時,download task 可以從中斷的地方繼續(xù)傳輸,而其他 task 都需要重新開始。當(dāng)調(diào)用- cancel 方法后,task 變?yōu)?canceling 狀態(tài),在發(fā)送給 delegate 的URLSession:task:didCompleteWithError:消息中,error 參數(shù)的 domain 為NSURLErrorDomain,code 為NSURLErrorCancelled。
*/
@property (readonly) NSURLSessionTaskState state;
@property (nullable, readonly, copy) NSError *error;
- (void)suspend;
- (void)resume;
/*
優(yōu)先級
task 有一個priority屬性,接受0到1之間的浮點(diǎn)數(shù),通過每一個 task 不同的 priority 值,可以提示系統(tǒng) task 執(zhí)行的優(yōu)先級,1為最高,0為最低。默認(rèn)值是NSURLSessionTaskPriorityDefault,即 0.5。系統(tǒng)提供了3個常量值:
NSURLSessionTaskPriorityDefault //0.5
NSURLSessionTaskPriorityLow // 0
NSURLSessionTaskPriorityHigh // 1
*/
@property float priority API_AVAILABLE(macos(10.10), ios(8.0), watchos(2.0), tvos(9.0));
NSURLSessionDataTask是NSURLSessionTask的子類,無單獨(dú)API。(主要使用在請求一些比較簡單的數(shù)據(jù),比如我們常用的JSON數(shù)據(jù)。)
NSURLSessionUploadTask是NSURLSessionDataTask的子類,無單獨(dú)API。(這個和上面那個task對應(yīng),主要是給服務(wù)器發(fā)送文件數(shù)據(jù)所使用的。)
NSURLSessionDownloadTask是NSURLSessionTask的子類,主要API如下(這個主要使用在進(jìn)行一些文件的下載,它可以針對一些大文件的網(wǎng)絡(luò)請求做更多的處理, 比如獲取下載進(jìn)度,文件的斷點(diǎn)續(xù)傳等等牛逼事情。)
/*
調(diào)用了基類NSURLSessionTask中的- cancel方法,參數(shù) completionHandler 要求傳入一個 block,用來處理已傳輸?shù)臄?shù)據(jù) resume data,這個 resume data 將來可用于 session 的- downloadTaskWithResumeData:方法,以便繼續(xù)中斷的下載。
*/
- (void)cancelByProducingResumeData:(void (^)(NSData * _Nullable resumeData))completionHandler;
NSURLSessionStreamTask是NSURLSessionTask的子類,主要API如下(提供TCP/IP的一個鏈接入口,方便進(jìn)行傳輸。)
/*
針對直接進(jìn)行TCP/IP連接的網(wǎng)絡(luò)操作API,此次帶來新的NSURLSessionStreamTask來,
代替NSInputStream和NSOutputStream,并且API使用起來便捷容易。
*/
- (void)readDataOfMinLength:(NSUInteger)minBytes maxLength:(NSUInteger)maxBytes timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSData * _Nullable data, BOOL atEOF, NSError * _Nullable error))completionHandler;
/*
異步寫數(shù)據(jù)操作
*/
- (void)writeData:(NSData *)data timeout:(NSTimeInterval)timeout completionHandler:(void (^) (NSError * _Nullable error))completionHandler;
- (void)captureStreams;
- (void)closeWrite;
- (void)closeRead;
- (void)startSecureConnection;
- (void)stopSecureConnection;
NSURLSessionTaskMetrics 和 NSURLSessionTaskTransactionMetrics
對發(fā)送請求/DNS查詢/TLS握手/請求響應(yīng)等各種環(huán)節(jié)時間上的統(tǒng)計。更易于我們檢測,分析我們App的請求緩慢到底是發(fā)生在哪個環(huán)節(jié),并對此進(jìn)行優(yōu)化提升我們APP的性能,NSURLSessionTaskMetrics對象與NSURLSessionTask對象一一對應(yīng)。每個NSURLSessionTaskMetrics對象內(nèi)有3個屬性 :
taskInterval : task從開始到結(jié)束總共用的時間
redirectCount : task重定向的次數(shù)
transactionMetrics : 一個task從發(fā)出請求到收到數(shù)據(jù)過程中派生出的每個子請求,它是一個裝著許多NSURLSessionTaskTransactionMetrics對象的數(shù)組。
API很簡單, 就一個方法 : - (void)URLSession: task: didFinishCollectingMetrics:, 當(dāng)收集完成的時候就會調(diào)用該方法.
NSURLSessionTaskMetrics主要API如下
*/
@property (copy, readonly) NSArray<NSURLSessionTaskTransactionMetrics *> *transactionMetrics;
@property (copy, readonly) NSDateInterval *taskInterval;
@property (assign, readonly) NSUInteger redirectCount;
-(instancetype)init;
NSURLSessionTaskTransactionMetrics主要API如下
@property (copy, readonly) NSURLRequest *request;
@property (nullable, copy, readonly) NSURLResponse *response;
@property (nullable, copy, readonly) NSDate *fetchStartDate;
@property (nullable, copy, readonly) NSDate *domainLookupStartDate;
@property (nullable, copy, readonly) NSDate *domainLookupEndDate;
@property (nullable, copy, readonly) NSDate *connectStartDate;
@property (nullable, copy, readonly) NSDate *secureConnectionStartDate;
@property (nullable, copy, readonly) NSDate *secureConnectionEndDate;
@property (nullable, copy, readonly) NSDate *connectEndDate;
@property (nullable, copy, readonly) NSDate *requestStartDate;
@property (nullable, copy, readonly) NSDate *requestEndDate;
@property (nullable, copy, readonly) NSDate *responseStartDate;
@property (nullable, copy, readonly) NSDate *responseEndDate;
@property (nullable, copy, readonly) NSString *networkProtocolName;
@property (assign, readonly, getter=isProxyConnection) BOOL proxyConnection;
@property (assign, readonly, getter=isReusedConnection) BOOL reusedConnection;
@property (assign, readonly) NSURLSessionTaskMetricsResourceFetchType resourceFetchType;
-(instancetype)init;
NSURLSession的優(yōu)勢和好處
1.后臺上傳和下載 : 當(dāng)你創(chuàng)建NSURLSession的時候你只需配置一個選項(xiàng)即可,你便可以進(jìn)行所有的后臺網(wǎng)絡(luò)任務(wù)。這將有對你的電池壽命有利,它支持UIKit多任務(wù)并且當(dāng)切換線程的時候使用相同的代理模型。
2.使你的網(wǎng)絡(luò)操作可以暫停和恢復(fù) :你稍后將會看到,任何使用NSURLSession API的網(wǎng)絡(luò)任務(wù)都可以被暫停,停止,重新開始。而沒有使用NSOperation子類的必要。
3.可配置的容器:對于放進(jìn)里面的請求而言每一個NSURLSession都是可配置的。例如,假如你需要設(shè)置一個HTTP header選項(xiàng),你只需要設(shè)置一次然后每個在session中的請求就都會有相同的配置了。
4.可子類化和私密存儲: NSURLSession是可子類化的并且你可以配置一個session用來作為私密存儲在某個會話中。這允許你擁有私密存儲對象在全局狀態(tài)下。
5.優(yōu)化的授權(quán)處理機(jī)制:授權(quán)被完成基于某個特定的連接。當(dāng)使用NSURLConnection的時候假如發(fā)生了一處授權(quán)改變,這個改變將返回一個隨意的請求,你不能確定你具體得到的那個。使用NSURLSession的話,代理回來處理授權(quán)。
6.豐富的代理模型:NSURLConnection有些基于block的同步方法,然而代理就不能使用它們了。當(dāng)一個請求建立了無論它是成功還是失敗,哪怕需要授權(quán)。使用NSURLSession就就可以混合接入,使用基于block的異步方法同時也可以設(shè)置代理來處理授權(quán)。
7.通過文件系統(tǒng)上傳和下載:蘋果鼓勵把(文件內(nèi)容)數(shù)據(jù)跟(URL和一些設(shè)置)元數(shù)據(jù)分開。
NSURLSession與NSURLConnection 的不同主要表現(xiàn)在以下幾方面:
(1) NSURLConnection 是 iOS2.0后推出的
NSURLSession 是iOS7.0后推出的,用于代替 NSURLConnection.
(2)下載任務(wù)方式
NSURLConnection 使用異步回調(diào),先將數(shù)據(jù)下載到內(nèi)存,等下載完畢后,再寫入沙盒.如果文件很大,會導(dǎo)致內(nèi)存暴漲; 并且,使用異步回調(diào)無法監(jiān)聽下載進(jìn)度.所以使用 NSURLConnection下載的時候,使用代理回調(diào)監(jiān)聽下載進(jìn)度,并且下載過程中要手動管理內(nèi)存,使用起來比較麻煩.而使用NSURLSession的時候,block 和代理可以同時起作用,并且可以直接從文件系統(tǒng)上傳、下載,不會出現(xiàn)內(nèi)存暴漲的情況. 下載文件的時候,默認(rèn)會將文件下載到沙盒的 tmp文件夾中,不會占多少用內(nèi)存. 但是在下載完成后,會刪除文件,所以要在下載完成或者其他需要的地方,增加保存文件的代碼.
(3)請求方式的控制
NSURLConnection實(shí)例化對象,實(shí)例化開始,默認(rèn)請求就發(fā)送(同步發(fā)送),不需要調(diào)用start方法。而cancel 可以停止請求的發(fā)送,停止后不能繼續(xù)訪問,需要創(chuàng)建新的請求。NSURLSession有三個控制請求的方法,取消(cancel),暫停(suspend),繼續(xù)(resume),暫停后可以通過繼續(xù)恢復(fù)當(dāng)前的請求任務(wù)。
(4)斷點(diǎn)續(xù)傳實(shí)現(xiàn)方式
NSURLConnection進(jìn)行斷點(diǎn)下載,通過設(shè)置訪問請求的HTTPHeaderField的Range屬性,開啟運(yùn)行循環(huán),NSURLConnection的代理方法作為運(yùn)行循環(huán)的事件源,接收到下載數(shù)據(jù)時代理方法就會持續(xù)調(diào)用,并使用NSOutputStream(或者通過文件指針)管道流進(jìn)行數(shù)據(jù)保存。NSURLSession進(jìn)行斷點(diǎn)下載,當(dāng)暫停下載任務(wù)后,如果 downloadTask (下載任務(wù))為非空,調(diào)用 cancelByProducingResumeData:(void (^)(NSData *resumeData))completionHandler 這個方法,這個方法接收一個參數(shù),完成處理代碼塊,這個代碼塊有一個 NSData 參數(shù) resumeData,如果 resumeData 非空,我們就保存這個對象到視圖控制器的 resumeData 屬性中。在點(diǎn)擊再次下載時,通過調(diào)用 [ [self.session downloadTaskWithResumeData: self.resumeData]resume]方法進(jìn)行繼續(xù)下載操作。經(jīng)過以上比較可以發(fā)現(xiàn),使用NSURLSession進(jìn)行斷點(diǎn)下載更加便捷。
(5) NSURLSession 可以設(shè)置配置信息
NSURLSession的構(gòu)造方法
(sessionWithConfiguration: delegate:delegateQueue)中有一個 NSURLSessionConfiguration類的參數(shù)可以設(shè)置配置信息,其決定了cookie,安全和高速緩存策略,最大主機(jī)連接數(shù),資源管理,網(wǎng)絡(luò)超時等配置。NSURLConnection不能進(jìn)行這個配置,相比于 NSURLConnection 依賴于一個全局的配置對象,缺乏靈活性而言,NSURLSession 有很大的改進(jìn)了。
NSURLSession可以設(shè)置三種配置信息,分別通過調(diào)用三個類方法返回配置對象:
+(NSURLSessionConfiguration *) defaultSessionConfiguration,配置信息使用基于硬盤的持久化Cache,保存用戶的證書到鑰匙串,使用共享cookie存儲;
+(NSURLSessionConfiguration *)ephemeralSessionConfiguration 配置信息和default大致相同。除了,不會把cache,證書,或者任何和Session相關(guān)的數(shù)據(jù)存儲到硬盤,而是存儲在內(nèi)存中,生命周期和Session一致。比如瀏覽器無痕瀏覽等功能就可以基于這個來做;
+(NSURLSessionConfiguration *) backgroundSessionConfigurationWithIdentifier:(NSString *)identifier 配置信息可以創(chuàng)建一個可以在后臺甚至APP已經(jīng)關(guān)閉的時候仍然在傳輸數(shù)據(jù)的session。
注意,后臺Session一定要在創(chuàng)建的時候賦予一個唯一的identifier,這樣在APP下次運(yùn)行的時候,能夠根據(jù)identifier來進(jìn)行相關(guān)的區(qū)分。如果用戶關(guān)閉了APP,IOS 系統(tǒng)會關(guān)閉所有的background Session。而且,被用戶強(qiáng)制關(guān)閉了以后,IOS系統(tǒng)不會主動喚醒APP,只有用戶下次啟動了APP,數(shù)據(jù)傳輸才會繼續(xù)。
(6)NSURLSession 支持HTTP 2.0
鏈接
http://ios.jobbole.com/93098/
https://yq.aliyun.com/articles/221561
http://www.guiyongdong.com/2016/11/18/NSURLSession%E4%B8%8ENSURLConnection%E5%8C%BA%E5%88%AB/