2014-10-03 110 views
7

我正在嘗試使用NSURLSessionDownloadTask,並利用Apple內置的URL緩存功能。我已經成功地得到了高速緩存使用NSURLSessionDataTask使用下面的代碼時的工作:我可以在iOS上使用HTTP緩存和NSURLSessionDownloadTask嗎?

- (void)downloadUsingNSURLSessionDataTask:(NSURL *)url { 
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; 
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
    NSURLSessionDataTask *dataTask = [session dataTaskWithRequest:request]; 
    [dataTask resume]; 
} 

- (void)cachedDataTaskTest { 
    // This call performs an HTTP request 
    [self downloadUsingNSURLSessionDataTask:[NSURL URLWithString:@"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"]]; 
    [NSThread sleepForTimeInterval:1]; 

    // This call returns the locally cached copy, and no HTTP request occurs 
    [self downloadUsingNSURLSessionDataTask:[NSURL URLWithString:@"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"]]; 
} 

不過,我需要執行的,我必須使用NSURLDownloadTask後臺下載。當我切換到這個緩存行爲不會發生。

- (void)downloadUsingNSURLSessionDownloadTask:(NSURL *)url { 
    NSURLSessionConfiguration *sessionConfig = [NSURLSessionConfiguration defaultSessionConfiguration]; 
    NSURLSession *session = [NSURLSession sessionWithConfiguration:sessionConfig delegate:self delegateQueue:nil]; 
    NSURLRequest *request = [NSURLRequest requestWithURL:url]; 
    NSURLSessionDownloadTask *downloadTask = [session downloadTaskWithRequest:request]; 
    [downloadTask resume]; 
} 

- (void)cachedDownloadTaskTest { 
    // This call performs an HTTP request 
    [self downloadUsingNSURLSessionDownloadTask:[NSURL URLWithString:@"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"]]; 
    [NSThread sleepForTimeInterval:1]; 

    // This call also performs an HTTP request 
    [self downloadUsingNSURLSessionDownloadTask:[NSURL URLWithString:@"http://ajax.googleapis.com/ajax/libs/jquery/1.7.1/jquery.min.js"]]; 
} 

This documentation蘋果表示NSURLDownloadTasks不叫URLSession:dataTask:willCacheResponse:completionHandler:委託方法,因此它不可能爲你的應用程序掛接到緩存的生命週期。我的猜測是,這意味着高速緩存對於這些任務根本不可用,但對此沒有明確說明。

  • 對於數據任務,所述NSURLSession對象調用委託的URLSession:dataTask:willCacheResponse:completionHandler:方法。然後你的 應用程序應該決定是否允許緩存。如果您不執行此方法,則默認行爲是使用會話的配置對象中指定的緩存 策略。
  • 任何人都可以證實此預感NSURLSessionDownloadTasks根本不支持緩存?是否有可能在後臺任務中利用Apple的HTTP緩存行爲?

    +0

    你爲什麼要重寫'willCacheResponse'? – quellish 2014-10-10 06:31:51

    +0

    我不想重寫'willCacheResponse',但我注意到你不能覆蓋它的NSURLDownloadTasks,並且懷疑這表明這些任務根本不支持緩存。 – 2014-10-10 09:15:27

    回答

    8

    NSURLSessionDownloadTask使用在應用程序進程外執行下載的系統服務(守護程序)執行工作。因此,實際上爲下載任務調用的委託回調比NSURLSessionDataTask更有限。如Life Cycle of a URL Session所述,數據任務委託將接收回調來自定義緩存行爲,而下載任務委託則不會。

    下載任務應使用NSURLRequest指定的高速緩存策略,並應使用NSURLSessionConfiguration指定的高速緩存存儲器(如果沒有,請提交錯誤)。默認緩存策略是NSURLRequestUseProtocolCachePolicy,默認URL緩存存儲是非後臺和非臨時配置的共享URL緩存。 URLSession:dataTask:willCacheResponse:completionHandler:的代表回調不是實際發生的更高緩存的好指標。

    如果您使用的是默認的會話配置創建一個NSURLSessionDownloadTask不定製的NSURLRequest S中的高速緩存策略,緩存已經發生。

    +0

    感謝您的回覆。我發現'NSURLRequest'中的'NSURLRequestUseProtocolCachePolicy'不在'NSURLSessionDownloadTask'中。如果我可以在獨立應用程序中重現此問題,我會按照您的建議發佈錯誤報告。 – 2014-10-15 23:06:03

    +0

    你看到的行爲是什麼? – quellish 2014-10-16 00:36:30

    +0

    我已經構建了一個框架測試項目,允許您在檢查通過Charles的HTTP流量時觸發下載和數據任務。所有初始的'NSURLSessionDownloadTask'請求都會發出HTTP請求,所以不會發生緩存。第一個'NSSessionDataTask'調用一個請求,但這兩種類型的後續請求都不會調用HTTP請求,因爲iOS使用的是緩存副本。本質上'NSURLSessionDownloadTask'將使用現有的緩存,但不添加到它。看到這個項目來演示這個:https://github.com/nickstreet/CacheTest – 2014-10-16 23:40:04

    5

    它看起來像NSURLSessionDownloadTask不會緩存,通過設計。

    NSURLSessionConfiguration文檔

    defaultSessionConfiguration方法進行了說明:

    默認會話配置使用持久性基於磁盤的緩存(當結果被下載到文件除外)並存儲用戶鑰匙串中的憑證。

    但是,沒有其他構造函數被記錄爲排除上面的斜體異常。我也測試了backgroundSessionConfigurationWithIdentifier,它似乎也沒有做這項工作。

    此外,requestCachePolicy也不提供任何方式的例外。

    NSURLSessionDownloadTask運行時效率

    NSURLSessionDownloadTask傳入的數據寫入到一個臨時文件中。當它完成文件時,它會通知委託或完成處理程序。最後它刪除文件。

    儘管它可以簡單地將文件移動到緩存中,但它必須處理實際修改文件的委託或完成處理程序,從而更改其緩存表示,甚至將文件移動到永久位置無法跟蹤。

    它可以在之前複製文件通知委託或完成處理程序,但這對於大型文件將是低效的。

    它可以保持文件只讀,但在iOS 8.0上似乎沒有這樣做。

    因此,系統不太可能執行任何緩存下載任務。

    解決方法

    最好的辦法是使用NSURLSessionDataTask,那麼當你委託的URLSession:dataTask:didReceiveData:方法被調用,傳入的數據追加到自己的文件。下次您使用NSURLSessionDataTask時,您可以在一次調用URLSession:dataTask:didReceiveData:時獲得緩存數據。

    相關問題