版本記錄
版本號 | 時間 |
---|---|
V1.0 | 2018.03.13 |
前言
我們做APP發(fā)起網(wǎng)絡請求,一般都是使用框架,這些框架的底層也都是蘋果的API,接下來幾篇就一起來看一下和網(wǎng)絡有關(guān)的幾個類样刷。感興趣的可以看上面幾篇文章。
1. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類 (一) —— NSURLSession
2. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(二) —— NSURLRequest和NSMutableURLRequest
3. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(三) —— NSURLConnection
4. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(四) —— NSURLSession和NSURLConnection的區(qū)別
5. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(五) —— 關(guān)于NSURL加載系統(tǒng)(一)
6. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(六) —— 使用NSURLSession(二)
7. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(七) —— URL數(shù)據(jù)的編碼和解碼(三)
8. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(八) —— 處理重定向和其他請求更改(四)
9. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(九) —— 身份驗證挑戰(zhàn)和TLS鏈驗證(五)
10. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(十) —— 理解獲取緩存(六)
11. 詳細解析幾個和網(wǎng)絡請求有關(guān)的類(十一) —— Cookies和自定義協(xié)議(七)
回顧
上一篇主要講述關(guān)于Cookies和自定義協(xié)議览爵,這一篇我們主要看一下URL Session的生命周期置鼻。
Life Cycle of a URL Session - URL Session的生命周期
您可以通過兩種方式使用NSURLSession API
:使用系統(tǒng)提供的代理或使用您自己的代理。一般來說蜓竹,如果您的應用程序執(zhí)行以下任何操作箕母,您必須使用您自己的代理:
- 當您的應用程序未運行時,使用后臺會話下載或上傳內(nèi)容俱济。
- 執(zhí)行自定義驗證嘶是。
- 執(zhí)行自定義SSL證書驗證。
- 決定傳輸是下載到磁盤還是根據(jù)服務器返回的MIME類型或其他類似標準顯示蛛碌。
- 上傳來自正文流的數(shù)據(jù)(與NSData對象相反)聂喇。
- 以編程方式限制緩存。
- 以編程方式限制HTTP重定向蔚携。
如果您的應用不需要執(zhí)行任何這些操作希太,則您的應用可以使用系統(tǒng)提供的代理。根據(jù)您選擇的技術(shù)酝蜒,您應該閱讀以下部分之一:
- 使用Life Cycle of a URL Session with System-Provided Delegates提供了一個輕量級的視圖誊辉,顯示您的代碼如何創(chuàng)建和使用URL會話。即使您打算編寫自己的代理亡脑,也應該閱讀本節(jié)芥映,因為它可以讓您完整了解代碼的配置對象并使用它。
- 使用Life Cycle of a URL Session with Custom Delegates提供了URL會話操作中每個完整參考步驟远豺。您應參考本節(jié)以幫助您了解會話如何與其代理進行交互奈偏。特別是,這解釋了何時調(diào)用每個代理方法躯护。
Life Cycle of a URL Session with System-Provided Delegates - 使用系統(tǒng)提供的代理的URL會話的生命周期
如果您在未提供代理對象的情況下使用NSURLSession類惊来,則系統(tǒng)提供的委托將為您處理許多細節(jié)。這是您的應用程序必須完成的方法調(diào)用的基本順序棺滞,以及在使用系統(tǒng)提供的代理使用NSURLSession時應用程序接收到的完成處理程序調(diào)用裁蚁。
- 創(chuàng)建會話配置。對于后臺會話继准,此配置必須包含唯一標識符枉证。存儲該標識符,并在應用程序崩潰或終止或掛起時使用該標識符與會話重新關(guān)聯(lián)移必。
- 創(chuàng)建一個會話室谚,指定一個配置對象和一個nil代理。
- 在每個表示資源請求的會話中創(chuàng)建任務對象。
每個任務都以暫停狀態(tài)開始。在您的應用程序調(diào)用任務的resume方法后,它開始下載指定的資源仅仆。任務對象是NSURLSessionTask-NSURLSessionDataTask,NSURLSessionUploadTask或NSURLSessionDownloadTask
的子類陈瘦,具體取決于您嘗試實現(xiàn)的行為。
- 在每個表示資源請求的會話中創(chuàng)建任務對象。
盡管您的應用程序可以(并且通常應該)向會話添加多個任務潮售,但為了簡單起見痊项,其余步驟按照單個任務來描述生命周期。
重要提示:如果您在未提供委托的情況下使用NSURLSession類酥诽,則您的應用程序必須使用帶有completionHandler參數(shù)的調(diào)用來創(chuàng)建任務线婚,否則它無法從類中獲取數(shù)據(jù)。
- 對于下載任務盆均,在從服務器傳輸期間塞弊,如果用戶通知您的應用程序暫停下載,則通過調(diào)用cancelByProducingResumeData:方法來取消該任務泪姨。稍后游沿,將返回的resume數(shù)據(jù)傳遞給
downloadTaskWithResumeData:
或downloadTaskWithResumeData:completionHandler:
方法以創(chuàng)建一個新的下載任務,以繼續(xù)下載肮砾。
- 對于下載任務盆均,在從服務器傳輸期間塞弊,如果用戶通知您的應用程序暫停下載,則通過調(diào)用cancelByProducingResumeData:方法來取消該任務泪姨。稍后游沿,將返回的resume數(shù)據(jù)傳遞給
- 當任務完成時诀黍,NSURLSession對象調(diào)用任務的完成處理程序。
注意:NSURLSession不會通過錯誤參數(shù)報告服務器錯誤仗处。您的應用程序通過error參數(shù)收到的唯一錯誤是客戶端錯誤眯勾,例如無法解析主機名或連接到主機。
URL Loading System Error Codes
中描述了錯誤代碼婆誓。通過NSHTTPURLResponse
對象中的HTTP狀態(tài)代碼報告服務器端錯誤吃环。有關(guān)更多信息,請閱讀NSHTTPURLResponse和NSURLResponse類的文檔洋幻。
- 當您的應用程序不再需要會話時郁轻,通過調(diào)用invalidateAndCancel(取消未完成的任務)或finishTasksAndInvalidate(以允許未完成的任務在使對象失效之前完成)來使其失效。
Life Cycle of a URL Session with Custom Delegates - 自定義代理的URL會話的生命周期
您通澄牧簦可以在不提供代理的情況下使用NSURLSession
API好唯。但是,如果您使用NSURLSession
API進行后臺下載和上載燥翅,或者您需要以非默認方式處理身份驗證或緩存骑篙,則必須提供遵循會話代理協(xié)議的代理,一個或多個任務代理協(xié)議或這些協(xié)議的一些組合森书。這個代理有許多用途:
- 與下載任務一起使用時靶端,NSURLSession對象使用代理為您的應用程序提供文件URL谎势,以便它可以獲取下載的數(shù)據(jù)。所有后臺下載和上傳都需要代理躲查。這些代理必須提供
NSURLSessionDownloadDelegate
協(xié)議中的所有代理方法。 - 代理們可以處理特定的認證挑戰(zhàn)译柏。
- 代理提供正文流以將基于流的數(shù)據(jù)上傳到遠程服務器镣煮。
- 代理可以決定是否遵循HTTP重定向。
- NSURLSession對象使用代理為您的應用程序提供每次傳輸?shù)臓顟B(tài)鄙麦。數(shù)據(jù)任務代理既可以接收初始調(diào)用(可以將請求轉(zhuǎn)換為下載)典唇,也可以接收隨后的調(diào)用,這些調(diào)用在從遠程服務器到達時提供數(shù)據(jù)片段胯府。
- 代理是NSURLSession對象在傳輸完成時可以告訴您的應用程序的一種方式介衔。
如果您正在使用具有URL會話的自定義代理(后臺任務需要),則URL會話的完整生命周期更加復雜骂因。以下是您的應用程序必須進行的方法調(diào)用的基本順序炎咖,以及使用帶有自定義代理的NSURLSession時你的APP接收的代理調(diào)用。
- 創(chuàng)建會話配置寒波。對于后臺會話乘盼,此配置必須包含唯一標識符。存儲該標識符俄烁,并在應用程序崩潰或終止或掛起時使用該標識符與會話重新關(guān)聯(lián)绸栅。
- 創(chuàng)建一個會話,指定一個配置對象以及一個可選的代理页屠。
- 在每個表示資源請求的會話中創(chuàng)建任務對象粹胯。每個任務都以暫停狀態(tài)開始。在您的應用程序調(diào)用任務resume方法后辰企,它開始下載指定的資源风纠。任務對象是
NSURLSessionTask-NSURLSessionDataTask,NSURLSessionUploadTask或NSURLSessionDownloadTask
的子類牢贸,具體取決于您嘗試實現(xiàn)的行為议忽。盡管您的應用程序可以(并且通常應該)向會話添加多個任務,但為了簡單起見十减,下面其余步驟按照單個任務來描述生命周期栈幸。
- 在每個表示資源請求的會話中創(chuàng)建任務對象粹胯。每個任務都以暫停狀態(tài)開始。在您的應用程序調(diào)用任務resume方法后辰企,它開始下載指定的資源风纠。任務對象是
-
- 如果遠程服務器返回一個狀態(tài)碼,該狀態(tài)碼指示需要身份驗證帮辟,并且該身份驗證需要連接級別質(zhì)詢(如SSL客戶端證書)速址,則NSURLSession將調(diào)用身份驗證質(zhì)詢代理方法。
- 對于會話級挑戰(zhàn)-
NSURLAuthenticationMethodNTLM由驹,NSURLAuthenticationMethodNegotiate芍锚,NSURLAuthenticationMethodClientCertificate或NSURLAuthenticationMethodServerTrust
-NSURLSession
對象調(diào)用會話委托的URLSession:didReceiveChallenge:completionHandler:
方法昔园。如果您的應用程序未提供會話代理方法,則NSURLSession對象會調(diào)用任務代理的URLSession:task:didReceiveChallenge:completionHandler:
方法來處理該挑戰(zhàn)并炮。 - 對于非會話級挑戰(zhàn)(所有其他挑戰(zhàn))默刚,
NSURLSession
對象調(diào)用會話代理的URLSession:task:didReceiveChallenge:completionHandler:
方法來處理挑戰(zhàn)。如果您的應用程序提供了會話代理逃魄,并且您需要處理身份驗證荤西,那么您必須在任務級別處理身份驗證,或者提供明確調(diào)用每會話處理程序的任務級別處理程序伍俘。會話代理的URLSession:didReceiveChallenge:completionHandler:
方法低于非會話級別的挑戰(zhàn)不會調(diào)用邪锌。
注意:
Kerberos
身份驗證是透明處理的。
如果上傳任務的認證失敗癌瘾,如果任務的數(shù)據(jù)是從流中提供的觅丰,則NSURLSession
對象將調(diào)用代理的URLSession:task:needNewBodyStream:代理方法。代理必須提供一個新的NSInputStream
對象來為新的請求提供正文數(shù)據(jù)妨退。
有關(guān)為NSURLSession
編寫身份驗證代理方法的更多信息妇萄,請參閱Authentication Challenges and TLS Chain Validation。
-
- 在收到HTTP重定向響應后咬荷,
NSURLSession
對象調(diào)用代理的URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler:方法嚣伐。該代理方法調(diào)用提供的NSURLRequest
對象(遵循重定向),新的NSURLRequest對象(重定向到不同的URL)或nil(將重定向的響應主體視為有效的響應并將其返回)完成處理程序作為結(jié)果)萍丐。
- 如果遵循重定向轩端,請返回到步驟4(驗證質(zhì)詢處理)。
- 如果代理沒有實現(xiàn)此方法逝变,則重定向會跟隨最大數(shù)量的重定向基茵。
- 在收到HTTP重定向響應后咬荷,
- 對于通過調(diào)用ddownloadTaskWithResumeData:或downloadTaskWithResumeData:completionHandler:創(chuàng)建的(重新)下載任務,
NSURLSession
使用新任務對象調(diào)用代理的URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes:方法壳影。
- 對于通過調(diào)用ddownloadTaskWithResumeData:或downloadTaskWithResumeData:completionHandler:創(chuàng)建的(重新)下載任務,
- 對于數(shù)據(jù)任務拱层,NSURLSession對象調(diào)用代理的URLSession:dataTask:didReceiveResponse:completionHandler:方法。決定是否將數(shù)據(jù)任務轉(zhuǎn)換為下載任務宴咧,然后調(diào)用完成回調(diào)來繼續(xù)接收數(shù)據(jù)或下載數(shù)據(jù)根灯。如果您的應用程序選擇將數(shù)據(jù)任務轉(zhuǎn)換為下載任務,則NSURLSession將新下載任務作為參數(shù)調(diào)用代理的URLSession:dataTask:didBecomeDownloadTask:方法掺栅。在這次調(diào)用之后烙肺,代理不再接收來自數(shù)據(jù)任務的進一步回調(diào),并開始接收來自下載任務的回調(diào)氧卧。
- 如果任務是使用uploadTaskWithStreamedRequest:創(chuàng)建的桃笙,則NSURLSession將調(diào)用代理的URLSession:task:needNewBodyStream:方法來提供正文數(shù)據(jù)。
- 在將主體內(nèi)容初始上傳到服務器(如果適用)期間沙绝,代理會定期接收 URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend:報告上載進度的回調(diào)搏明。
- 在從服務器傳輸過程中鼠锈,任務代理會定期收到一個回調(diào)來報告?zhèn)鬏斶M度。對于下載任務星著,會話調(diào)用代理的URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:方法购笆,其中可以獲得成功寫入磁盤的字節(jié)數(shù)。對于數(shù)據(jù)任務虚循,會話會在接收到實際的數(shù)據(jù)段時調(diào)用委托的URLSession:dataTask:didReceiveData:方法同欠。
對于下載任務,在從服務器傳輸期間邮丰,如果用戶通知您的應用程序暫停下載行您,則通過調(diào)用cancelByProducingResumeData:方法取消該任務铭乾。
- 在從服務器傳輸過程中鼠锈,任務代理會定期收到一個回調(diào)來報告?zhèn)鬏斶M度。對于下載任務星著,會話調(diào)用代理的URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite:方法购笆,其中可以獲得成功寫入磁盤的字節(jié)數(shù)。對于數(shù)據(jù)任務虚循,會話會在接收到實際的數(shù)據(jù)段時調(diào)用委托的URLSession:dataTask:didReceiveData:方法同欠。
稍后剪廉,如果用戶要求您的應用程序繼續(xù)下載,請將所返回的resume數(shù)據(jù)傳遞給downloadTaskWithResumeData:或downloadTaskWithResumeData:completionHandler:方法以創(chuàng)建一個可繼續(xù)下載的新下載任務炕檩,然后轉(zhuǎn)到步驟3(創(chuàng)建并恢復任務對象)斗蒋。
- 對于數(shù)據(jù)任務,NSURLSession對象調(diào)用代理的URLSession:dataTask:willCacheResponse:completionHandler:方法笛质。然后你的應用程序應該決定是否允許緩存泉沾。如果您未實現(xiàn)此方法,則默認行為是使用會話配置對象中指定的緩存策略妇押。
- 如果下載任務成功完成跷究,則NSURLSession對象調(diào)用任務的URLSession:downloadTask:didFinishDownloadingToURL:方法并獲取臨時文件的位置。在此代理方法返回之前敲霍,您的應用必須從此文件讀取響應數(shù)據(jù)或?qū)⑵湟浦翍蒙诚淙萜髂夸浿械挠谰梦恢谩?/li>
- 當任何任務完成時俊马,NSURLSession對象調(diào)用返回錯誤對象或nil(如果任務成功完成)的代理的URLSession:task:didCompleteWithError:方法。如果任務失敗肩杈,則大多數(shù)應用程序都應該重試請求柴我,直到用戶取消下載或服務器返回錯誤,表明請求永遠不會成功扩然。但是艘儒,您的應用不應該立即重試。相反夫偶,它應該使用reachability API來確定服務器是否可聯(lián)通界睁,并且僅當它收到reachability已更改的通知時才應發(fā)出新請求。
如果可以恢復下載任務兵拢,則NSError
對象的userInfo
字典包含NSURLSessionDownloadTaskResumeData鍵的值晕窑。您的應用應該傳遞此值調(diào)用downloadTaskWithResumeData:或downloadTaskWithResumeData:completionHandler:創(chuàng)建一個新的下載任務,以繼續(xù)現(xiàn)有的下載卵佛。
如果任務無法恢復杨赤,您的應用程序應該創(chuàng)建一個新的下載任務并從頭開始重新啟動事務敞斋。
無論哪種情況,如果由于服務器錯誤以外的其他原因?qū)е聜鬏斒〖采堔D(zhuǎn)至步驟3(創(chuàng)建并恢復任務對象)植捎。
注意:
NSURLSession
不會通過錯誤參數(shù)報告服務器錯誤。代理通過error參數(shù)收到的唯一錯誤是客戶端錯誤阳柔,例如無法解析主機名或連接到主機焰枢。URL Loading System Error Codes
中描述了錯誤代碼。
通過NSHTTPURLResponse
對象中的HTTP狀態(tài)代碼報告服務器端錯誤舌剂。有關(guān)更多信息济锄,請閱讀NSHTTPURLResponse和NSURLResponse類的文檔。
- 如果響應是多部分編碼的霍转,那么會話可以再次調(diào)用代理的
didReceiveResponse
方法荐绝,然后再調(diào)用零個或多個額外的didReceiveData
調(diào)用。如果發(fā)生這種情況避消,請轉(zhuǎn)到步驟7(處理didReceiveResponse
調(diào)用)低滩。
- 如果響應是多部分編碼的霍转,那么會話可以再次調(diào)用代理的
- 當您不再需要會話時,通過調(diào)用
invalidateAndCancel
(取消未完成的任務)或finishTasksAndInvalidate
(以允許未完成的任務在使對象失效之前完成)來使其無效岩喷。在使會話無效之后恕沫,當所有未完成的任務已被取消或完成時,會話向委托發(fā)送一個URLSession:didBecomeInvalidWithError:
消息纱意。當該代理方法返回時婶溯,會話將處理其對代理的強烈引用。
- 當您不再需要會話時,通過調(diào)用
重要提示:會話對象保持對代理的強引用偷霉,直到您的應用程序明確地使會話失效迄委。如果您不會使會話失效,您的應用程序會泄漏內(nèi)存腾它。
如果您的應用取消正在進行的下載跑筝,則NSURLSession對象會像發(fā)生錯誤一樣調(diào)用代理的URLSession:task:didCompleteWithError:方法。
后記
本篇介紹了關(guān)于URL Session的生命周期問題瞒滴,喜歡的就給個贊或者點個關(guān)注~~~