Apple 文檔 NSURLSession 翻譯 - 管理下載內容的類

NSURLSession 類及其相關類為下載內容提供了接口。這個 API 提供了一系列豐富的代理方法來支持授權,而且讓你的 APP 在后臺被掛起時也能繼續下載。

通過代理服務器的和 SOCKS 網關為用戶配置好系統設置,NSURLSession 類完全支持 data, file, ftp, http, https類型的超鏈接。你也可以添加一些支持你自己定制的網絡協議或超鏈接(專門為你自己的 APP 所用)

重大說明!
NSURLSession 的 API 有很多你在看文檔時可能感覺并不重要,但實際上卻以很復雜的方式來共同發揮作用的類。用這個 API 之前,你應該看一下 URL Session Programming Guide 來了解這些類之間相互調用的一些概念。

通過 NSURLSession 的 API,你的 APP可以創建一個或者多個事務,其中的每一個事務都用來協助一組相關的數據來傳輸任務。比如,如果你在寫一個瀏覽器,你的 APP 可能在每一欄或是每一個窗口都創建了一個事務,可能一個用來進行交互,一個用來后臺下載。在每一個事務中,你的 APP 都添加了一些了的任務,其中的每一個任務就代表一個請求或是一個特定的 URL(必要時進行重定向)

給定 URL事務的這些任務共享一個事務配置 session,這個對象定義好了連接行為,比如通往同一個主機的相似連接的最大連接數,不管是通過蜂窩移動網絡還是別的方式來允許連接。session 的行為一部分是由創建這個配置對象時你調用的方法來決定:

  • 單例 shared session (沒有配置對象)用于普通請求。它像你自己創建的session一樣可定制,但是如果你的請求有限的話它是一個很好的起點,通過調用 sharedSession 來獲取這個 session??催@個方法的文檔來得到它的一些限制信息。

  • Default sessions 的行為和 shared session 差不多(除非你自己進行了深度定制),但你必須要通過代理方法得到增量數據。調用 NSURLSessionConfiguration 中的 defaultSessionConfiguration 方法來創建 Default session。

  • Ephemeral sessionsDefault sessions 很相似,但是不寫入 caches,cookies, 或credentials。
    調用 NSURLSessionConfiguration 中的 ephemeralSessionConfiguration 方法來創建 Ephemeral session。

  • Background sessions 可以在你的 APP 在后臺被掛起時進行上傳或下載。調用 NSURLSessionConfiguration 中的 backgroundSessionConfiguration: 方法來創建 background session

session 配置對象還包含了對 URL cache 和 cookie 存儲對象發起請求并處理相應的引用,具體取決于配置和請求類型。

當多種類型的事件發生時(比如授權失敗時,數據傳輸到服務器時,數據準備好緩存時等等)session 中的任務也會共享一個通用的代理來讓你提供和獲取相關信息。對于所有的后臺下載和上傳,你必須提供一個遵從 NSURLSessionDownloadDelegate 的 OC 協議。否則,如果你不需要任何由代理提供的特性,在你創建 session 時就給 delegate 傳 nil 來調用這個 API。

重大說明!
session 對你的 delegate 始終保持強引用,除非你的 app 退出或者 session已明確失效。如果你沒有使 session 失效,你的 app 將會內存溢出,直到它終止。

在 session 中,你創建了可上傳數據到服務器的任務,然后通過磁盤上的文件,或是內存中的一個或多個 NSData 對象來獲取數據。 NSURLSession 的 API 提供了三種類型的任務:

  • data tasks 通過 NSData 對象來發送和接受數據。 data tasks 用于與服務器進行簡短頻繁的請求。
  • Upload tasksdata tasks 類似,但是他們也可以發送數據(一般是通過文件的形式),也支持 app 后臺上傳。
  • Download tasks 通過文件的形式來獲取數據,并且支持 app 后臺上傳和下載。

和大多數網絡接口一樣,NSURLSession是高度異步的。它通過兩種方式中的其中一種來返回數據給 app,取決于你調用的方法:

  • 當傳輸成功或是發生錯誤時調用 completion handler block;
  • 當收到數據或是傳輸完成時調用 session 的代理方法。

除了通過代理來傳遞數據,如果你需要通過當前任務的狀態(給出一些狀態警示)做一些程序上的決定, NSURLSession的 API 統一提供了狀態和進度的屬性,方便查詢。

URL sessions 同樣支持取消,重啟,恢復,掛起任務,而且可以在他們停止的地方恢復掛起、取消、失敗了的下載。

URL Session Class 層級結構

NSURLSession API 由下面的類組成(下面的縮進顯示的是子類的關系)

除此之外,NSURLSession 還提供了4個代理, 訂了代理方法,你的 app 可以實現這些代理方法,提供對 session 和 task 更加細化的控制。

最終,NSURLSession 的 API 使用了很多類,這些類也同樣使用了其他的 API,比如 NSURLConnection 和 NSURLDownload。共同使用的類包括:

  • NSURL — 包含了 URL 的對象
  • NSURLRequest — 封裝與 URL 請求,包括 URL、 請求方法等等相關的元數據。
  • NSURLResponse— 封裝服務器相應的請求,如與 Content 的 MIME 類型和長度相關的元數據。
  • NSHTTPURLResponse — 給 HTTP請求添加特定的附加元數據,比如 response headers。
  • NSCachedURLResponse — 用來緩存服務器響應的 body data 封裝的一個NSURLResponse對象。

身份驗證和 TLS 定制

當服務器要求身份驗證或在 TLS 協商期間提供憑證時,URL Session 通過調用代理方法,讓你可以自定義處理身份驗證或證書驗證。

調用的代理方法取決于你是在處理 task 相關還是 session范圍內的挑戰。Table 1 給出了兩者之間的區別。

**Table 1 ** Session-level and connection-level challenges

Session-wide challenges Task-specific challenges
NSURLAuthenticationMethodNTLM NSURLAuthenticationMethodDefault
NSURLAuthenticationMethodNegotiate NSURLAuthenticationMethodHTTPBasic
NSURLAuthenticationMethodClientCertificate NSURLAuthenticationMethodHTTPDigest
NSURLAuthenticationMethodServerTrust -

對于 task 相關的挑戰, session 會調用代理的
URLSession:task:didReceiveChallenge:completionHandler: 方法。

對于 session 相關的授權挑戰,session 會調用代理的
URLSession:didReceiveChallenge:completionHandler: 方法,如果它不存在,則調用代理的URLSession:task:didReceiveChallenge:completionHandler: 方法。

當請求需要客戶端授權時,如果你沒有實現這些方法,URL Session 會通過下面的方式來嘗試授權:

  • 如果 URL中含有授權信息的話,通過請求的 URL 中的授權信息。
  • 在用戶的鑰匙串( 在 OS X 中)或是 app 的鑰匙串(在 iOS 中)尋找網絡密碼或是證書。

如果驗證不可用,或是服務器拒絕了驗證,那這個連接將會在沒有授權的情況下繼續。對于 HTTP 和 HTTPs 請求來說,連接會通過一個對應的 HTTP 狀態碼反應嘗試失敗, 也可能會提供可選擇的內容(比如私有網站的公開版本)。對于其他類型的 URL(比如 FTP),將會直接連接失敗。


erberos 身份驗證的處理是公開透明的。這里描述的委托方法不適用于 Kerberos 身份驗證。

App 傳輸安全 (ATS)

從 iOS9.0 和 OS X v10.11 開始,一種稱為App 傳輸安全(ATS)的安全特性在所有用作 HTTP 連接的 NSURLSession 中是默認啟用的。ATS 要求 HTTP 連接使用 HTTPS(RFC 2818)。

想了解更多信息,請看
Information Property List Key Reference 中的 NSAppTransportSecurity

使用 URL Session

使用 NSURLSession 類發起一個請求:

  1. 創建一個 session 配置。若是用作后臺的 session,這個配置必須包括一個 唯一標識(unique identifier)。 存儲這個標識, 當你的 app 崩潰或是被終止或是被掛起時用它來重連 session。
  2. 創建一個 session, 指定它的配置對象,或是代理。
  3. 在每個代表一個資源請求的 session 中創建 task 對象。這些 task 對象應該是
    NSURLSessionTaskNSURLSessionDataTask, NSURLSessionUploadTask, or NSURLSessionDownloadTask 的子類,具體用哪個取決于你想要做什么。

每個task 開始時都處于掛起狀態。你的 App 調用恢復任務后,它會開始下載其對應的資源。

在你開始一個 task 之后,session 會調用其代理方法,如下:

  1. 如果和服務器初始化握手需要一個連接 level 的挑戰(比如SSL 的客戶端證書),NSURLSession 會調用 URLSession:task:didReceiveChallenge:completionHandler: 或是 URLSession:didReceiveChallenge:completionHandler: 代理方法,如前面的 身份驗證和 TLS 定制 所述。 了解更多為 NSURLSession 寫一個授權代理方法的信息,請閱讀 read URL Session Programming Guide.

  2. 如果這個 task 的數據是由流提供的,NSURLSession 對象將會調用代理的 URLSession:task:needNewBodyStream: 代理方法來獲取一個 提供新請求的 body data 的 NSInputStream 對象。

  3. 在初始化上傳到服務器(如果可用的話)的 body 內容期間,代理會階段性接收 URLSession:task:didSendBodyData:totalBytesSent:totalBytesExpectedToSend: 的回調來報告上傳進度;

  4. 服務器發送一個響應;

  5. 如果響應表明需要授權,session 會調用代理方法
    URLSession:didReceiveChallenge:completionHandler: ,回到步驟2;

  6. 如果響應是一個 HTTP 重定向響應, NSURLSession 對象會調用代理方法
    URLSession:task:willPerformHTTPRedirection:newRequest:completionHandler: 代理方法會用提供的 NSRULRequest 對象(遵循重定向),或是新的 NSURLRequest 對象(如果需要重定向到一個不同的 URL 的話),或是 nil(將有效的響應作為重定向響應的 body,并將它作為結果返回) 來調用所提供的 completion handler 。

  • 如果你決定追蹤重定向,返回步驟2;
  • 如果代理沒有實現這個方法,這個重定向將會被重定向的最大數字跟進。
  1. 對于一個通過調用
    downloadTaskWithResumeData:
    downloadTaskWithResumeData:completionHandler: 方法創建的(重復)下載任務來說,NSURLSession 會對一個新的任務對象調用
    URLSession:downloadTask:didResumeAtOffset:expectedTotalBytes: 代理方法。

  2. 對于數據任務,NSURLSession 會調用
    URLSession:dataTask:didReceiveResponse:completionHandler: 代理方法,來決定是否要將 數據任務轉換成下載任務,然后調用完成回調來繼續接收或下載數據。 如果你的 app 選擇將數據任務轉換成下載任務,NSURLSession 會將這個新的下載任務作為一個參數來調用 URLSession:dataTask:didBecomeDownloadTask: 代理方法。調用完之后,代理不會從數據任務接收到進一步回調,而是從下載任務那里來接收回調;

  3. 在服務器傳輸過程中,代理會周期性地接收到一個 task-level 的回調方法來報告傳輸的進度。 對于數據任務,session 會在接收過程中通過真正的數據塊來調用
    URLSession:dataTask:didReceiveData: 代理方法。
    對于下載任務來說,session 會通過已經成功寫入磁盤的 bytes 來調用
    URLSession:downloadTask:didWriteData:totalBytesWritten:totalBytesExpectedToWrite: 代理方法。如果用戶告訴 app 來暫停下載,通過cancelByProducingResumeData: 然后,如果用戶要求 app 繼續下載任務,將返回的恢復數據給
    downloadTaskWithResumeData:
    downloadTaskWithResumeData:completionHandler: 方法來創建一個新的下載任務,來繼續下載。(返回步驟1)

  4. 對于數據任務,NSURLSession 對象可能會調用
    URLSession:dataTask:willCacheResponse:completionHandler: 方法。你的 app 應該來決定是否允許緩存。如果你沒有是現在合格方法,默認會使用 session 的配置對象中的緩存方案。

  5. 如果響應是由多個部分組成的編碼,session 會在didiRecieveReponse代理被多次調用之后再次調用 didRecieveData 代理方法。如果出現這樣的情況,回調步驟8(處理 didRecieveResponse回調)

  6. 如果下載任務成功完成, NSURLSession 對象會通過一個臨時文件的地址來調用任務的 URLSessionDownloadTask:didFinishDownloadingToURL: 方法。你的 app 必須從這個文件中讀取返回的數據,或是在這個代理方法 結束之前將它移到一個永久保存的地址。

  7. 任務完成時, NSURLSession 對象會通過一個錯誤對象或是 nil (如果任務成功完成)來調用 URLSession:task:didCompleteWithError:
    如果這個下載任務是可被重新喚起的,這個 NSError 對象的 userInfo 字典中會包含 key 為
    NSURLSessionDownloadTaskResumeData 的值。你要將這個值傳給
    downloadTaskWithResumeData:
    或是 downloadTaskWithResumeData:completionHandler: 來創建一個新的下載任務以繼續這個已經存在的下載任務。
    如果這個下載任務不能被重新喚起,你的 app 需要創建一個新的下載任務來從頭開始下載。
    不管是哪種情況,如果傳輸因任何服務器錯誤以外的原因而失敗,返回到步驟3(創建或喚起任務對象)。


NSURLSession 不會通過 error 參數返回任何的服務器錯誤。通過 error 參數返回的錯誤只會是服務器端錯誤,比如不能解決 hostname,不能連接到 host。error codes 信息可在 URL Loading System Error Codes 中查詢。
服務器端錯誤會通過 ** NSHTTPURLResponse** 對象中的HTTP 狀態碼來返回,了解更多信息,請閱讀 NSHTTPURLREsponseNSURLResponse 的文檔。

  1. 如果你不需要用到 session 了,可以通過調用 invalidateAndCancel(用來取消未完成的任務)或是 finishTasksAndInvalidate (在這個對象失效前完成未完成的任務)。 如果你不使這個session失效,它會在你的app終止時自動消失(除非它是一個含有正在進行的任務的后臺 session) session 失效后,當所有未完成的任務被取消或是完成時,session會調用 URLSession:didBecomeInvalidWithError: 方法。當代理方法返回時,session 會處置對代理的強引用。

如果你的app 取消了一個正在進行的下載任務, 當出現錯誤時,NSURLSession 對象會調用代理的 URLSession:task:didCompleteWithError: 方法。

后臺處理注意事項

因為重啟app(或是等待用戶重新喚起時)代價是相當高的,在后臺session中有些特性是不可用的。如下:

  • session 必須提供一個傳遞事件的代理,因為在傳輸進行中app可能會退出或是重啟,完成事件的回調 Block 是不支持的、(為了上傳和下載),這些代理在傳輸過程中表現是相同的;

  • 只有 HTTP 和 HTTPS 協議是被支持的。其他內置的網絡協議和用戶網絡協議都不被支持;

  • 只有上傳和下載是被支持的(沒有 data 任務);

  • 重定向一直被允許;

  • 全系統同時進行的后臺傳輸的數量是被限制的;

  • 如果后臺任務未能滿足指定系統吞吐量限制,可能會被取消。也就是說,如果一個長期運行的任務在一段時間內沒有發送或者接受足夠的數據,它可能會被取消,以后再被喚起。所以,如果可能的話,讓一個傳輸可被重新喚起是很重要的。

  • 如果后臺傳輸初始化時app是在后臺,那這個任務將被當做可裁剪的。換言之,它將被當做 配置對象的 discretionary 屬性為 true 的session中的一個任務。

  • 譯者注:也就是說如果你要傳輸大量的數據,最好設置這個屬性為YES,這樣的話系統會延遲傳輸,直到你手機接通電源或是連上 wifi。下載大數據什么的設置為YES就對了

如果這些限制和你 app 的需求有沖突,你可以在 non-background session 中將遠程資源下載到一個文件中。這樣,當你的用戶讓你的 iOS app 進入后臺或是退出你的 OS X app 時,可以通過調用 cacelByProducingResumeData: 方法來暫停任何進行中的下載任務。當用戶重新讓 app 進入前臺時恢復下載。如果你的 app 在你獲取到任何恢復的數據之前終止了,就不能再恢復下載了。


后臺 session 是為了優化傳輸少量很大的資源,在必要時可以進行續傳。如果可以,你可能想要調查優化服務器端行為的方法 ,來實現這樣的用法,比如:

  • 在終結點發起發送或接收 zip 或 tar格式的壓縮文件的請求,而不是分開調用多次;
  • 在終結點發起發送或接收在服務器和客戶端之間的增量差異的請求;
  • 在終結點發起一個可返回上傳ID的請求,這個ID可用來追蹤和恢復傳輸到服務器的數據;
  • 添加一個中間的web 服務器代理請求到規范的web服務器,以方便任何上述優化。

NSCopying 行為

session 和 task 對象都遵從 NSCopying 協議,如下:

  • 當你的app 拷貝一個session 或是 task 對象時,你會得到一個同樣的對象;
  • 當你的app拷貝一個配置對象時,你會得到一個你可以獨立地修改的拷貝對象。

線程安全

URL Session API 自身完全是線程安全的。你可以在任何一個線程上下文中隨意創建 session 和 task,而且,當你的代理方法調用提供的 完成回調時,它的工作已自動被安排在正確的代理隊列中。

警告
你的 URLSessionDidFinishEventsForBackgroundURLSession: 代理方法可能會在第二線程中被調用。但是,在iOS中,你完成那個方法時需要在
application:handleEventsForBackgroundURLSession:CompletionHandler: app 代理方法中調用completion handler。而且你必須在主線程中調用那個 completion handler。

創建 Session

+ sessionWithConfiguration:

+ sessionWithConfiguration:delegate:delegateQueue:

+ sharedSession

配置 Session

configuration Property

delegate Property

delegateQueue Property

sessionDescription Property

給 Session 添加數據任務

- dataTaskWithURL:

- dataTaskWithURL:completionHandler:

- dataTaskWithRequest:

- dataTaskWithRequest:completionHandler:

給 Session 添加下載任務

- downloadTaskWithURL:

- downloadTaskWithURL:completionHandler:

- downloadTaskWithRequest:

- downloadTaskWithRequest:completionHandler:

- downloadTaskWithResumeData:

- downloadTaskWithResumeData:completionHandler:

給 Session 添加上傳任務

- uploadTaskWithRequest:fromData:

- uploadTaskWithRequest:fromData:completionHandler:

- uploadTaskWithRequest:fromFile:

- uploadTaskWithRequest:fromFile:completionHandler:

- uploadTaskWithStreamedRequest:

給 Session添加流任務

- streamTaskWithHostName:port:- streamTaskWithNetService:

管理 Session

- finishTasksAndInvalidate

- flushWithCompletionHandler:

- getTasksWithCompletionHandler:

- invalidateAndCancel

- resetWithCompletionHandler:

常量

NSURLSession-Specific NSError userInfo Dictionary Keys

Background Task Cancellation reasons

Transfer Size Constant

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市,隨后出現的幾起案子,更是在濱河造成了極大的恐慌,老刑警劉巖,帶你破解...
    沈念sama閱讀 228,333評論 6 531
  • 序言:濱河連續發生了三起死亡事件,死亡現場離奇詭異,居然都是意外死亡,警方通過查閱死者的電腦和手機,發現死者居然都...
    沈念sama閱讀 98,491評論 3 416
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來,“玉大人,你說我怎么就攤上這事。” “怎么了?”我有些...
    開封第一講書人閱讀 176,263評論 0 374
  • 文/不壞的土叔 我叫張陵,是天一觀的道長。 經常有香客問我,道長,這世上最難降的妖魔是什么? 我笑而不...
    開封第一講書人閱讀 62,946評論 1 309
  • 正文 為了忘掉前任,我火速辦了婚禮,結果婚禮上,老公的妹妹穿的比我還像新娘。我一直安慰自己,他們只是感情好,可當我...
    茶點故事閱讀 71,708評論 6 410
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著,像睡著了一般。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發上,一...
    開封第一講書人閱讀 55,186評論 1 324
  • 那天,我揣著相機與錄音,去河邊找鬼。 笑死,一個胖子當著我的面吹牛,可吹牛的內容都是我干的。 我是一名探鬼主播,決...
    沈念sama閱讀 43,255評論 3 441
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼!你這毒婦竟也來了?” 一聲冷哼從身側響起,我...
    開封第一講書人閱讀 42,409評論 0 288
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎,沒想到半個月后,有當地人在樹林里發現了一具尸體,經...
    沈念sama閱讀 48,939評論 1 335
  • 正文 獨居荒郊野嶺守林人離奇死亡,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內容為張勛視角 年9月15日...
    茶點故事閱讀 40,774評論 3 354
  • 正文 我和宋清朗相戀三年,在試婚紗的時候發現自己被綠了。 大學時的朋友給我發了我未婚夫和他白月光在一起吃飯的照片。...
    茶點故事閱讀 42,976評論 1 369
  • 序言:一個原本活蹦亂跳的男人離奇死亡,死狀恐怖,靈堂內的尸體忽然破棺而出,到底是詐尸還是另有隱情,我是刑警寧澤,帶...
    沈念sama閱讀 38,518評論 5 359
  • 正文 年R本政府宣布,位于F島的核電站,受9級特大地震影響,放射性物質發生泄漏。R本人自食惡果不足惜,卻給世界環境...
    茶點故事閱讀 44,209評論 3 347
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望。 院中可真熱鬧,春花似錦、人聲如沸。這莊子的主人今日做“春日...
    開封第一講書人閱讀 34,641評論 0 26
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽。三九已至,卻和暖如春,著一層夾襖步出監牢的瞬間,已是汗流浹背。 一陣腳步聲響...
    開封第一講書人閱讀 35,872評論 1 286
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留,地道東北人。 一個月前我還...
    沈念sama閱讀 51,650評論 3 391
  • 正文 我出身青樓,卻偏偏與公主長得像,于是被迫代替她去往敵國和親。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 47,958評論 2 373

推薦閱讀更多精彩內容