2016-01-13 88 views
2

我在使用NSURLSession框架一些誤解,這就是爲什麼我決定從頭開始編寫小應用,而無需AFFramework/Alamofire。NSURLSessionUploadTask獲得效應初探數據

我有一個需要以下步驟上傳文件的API:

  1. POST文件數據
  2. 獲取響應(JSON)
  3. 後一些JSON領域api/save

我有這樣的配置背景會話:

let configuration = NSURLSessionConfiguration.backgroundSessionConfigurationWithIdentifier("myBackground") 
let session = NSURLSession(configuration: configuration, delegate: self, delegateQueue: nil) 

我實現2種方法:

func URLSession(session: NSURLSession, dataTask: NSURLSessionDataTask, didReceiveData data: NSData) 

其中I聚集所有數據

func URLSession(session: NSURLSession, task: NSURLSessionTask, didCompleteWithError error: NSError?) 

其中I這個數據變換分析到響應對象。這個響應對象對我來說非常重要。

一切正常,而應用程序是在前臺,但我在後臺的問題。

案例1

應用程序崩潰之後我開始上傳數據。據WWDC我需要實現

func application(application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler:() -> Void) 

didCompleteWithError方法調用此處理程序。但是,在調用此方法之前,我需要調用api/save從上傳的響應數據。 我如何獲得這些數據?

案例2

晴類似的案件。用戶在上傳過程中停止應用程序。比在幾秒鐘內加載應用程序,而會話與我的任務一起工作。現在會議電話didReceiveData,但當然,一些數據丟失。在這種情況下我應該怎麼做?如何恢復響應數據?

回答

2

你不提實現URLSessionDidFinishEventsForBackgroundURLSession(一NSURLSessionDelegate方法)。你也很想實現這一點。其基本過程是:

  • 在應用程序委託的handleEventsForBackgroundURLSession,你應該:

    • 啓動後臺NSURLSession(將開始接收所有的上傳相關的委託方法調用);和
    • 保存完成處理(但不調用它,還)。
  • 然後,在URLSessionDidFinishEventsForBackgroundURLSession(當你完成處理所有響應),你叫你handleEventsForBackgroundURLSession保存完成處理。 (請確保派遣是到主隊列。)

如果你正在做的一切,重新啓動的背景會話時,該didReceiveData電話會與應對您的各種上傳。

我只是做了一個快速測試,上傳五個20MB圖像,並立即終止應用程序。然後,即使應用程序沒有運行,我看到五個文件緩慢地顯示在我的服務器上(顯然是由守護進程處理的)。當所有五個都完成後,通過應用程序在後臺透明地重新啓動,handleEventsForBackgroundURLSession被調用(它重新啓動會話),它讓所有的didReceiveData調用快速被調用,並且當完成時,URLSessionDidFinishEventsForBackgroundURLSession被調用,我的應用程序只然後調用保存的完成處理程序。

根據爲什麼這不適用於您,沒有足夠的診斷問題。可能性包括:

  • 也許你不適當地終止了應用程序。您不能通過雙擊主頁按鈕並終止應用程序來終止應用程序;你必須讓它自己終止,或者出於診斷/測試的目的,我強迫它通過在代碼中調用exit(0)來終止。

  • 也許你在調用handleEventsForBackgroundURLSession時沒有重新啓動會話。

  • 也許您過早地調用了提供的完成處理程序(即在調用URLSessionDidFinishEventsForBackgroundURLSession之前)。

這很難說,但我懷疑還有埋藏您實現內在的東西,是不完全正確,很難說這是所提供的信息的基礎上什麼(假設它不是一個以上幾點)。不幸的是,調試這個後臺會話非常複雜,因爲當應用程序終止時,它不再連接到調試器,所以你不能輕鬆調試iOS自動重啓應用程序後發生的情況。就我個人而言,我要麼是NSLog消息,只要看設備控制檯(以及觀看服務器上顯示的內容),或者我在應用程序本身中構建一些持久性日誌記錄機制。

+0

謝謝您的很好的解釋。我將你的答案標記爲「正確」,因爲(我相信)它會涵蓋他人的問題。但是,我沒有運氣實現'URLSessionDidFinishEventsForBackgroundURLSession'。我重新啓動BG會話並獲得'URLSession(會話:NSURLSession,dataTask:NSURLSessionDataTask,didReceiveData數據:NSData的)'我得到以下數據:'會話:<__ NSURLBackgroundSession:0x1668c060> dataTask:<__ NSCFBackgroundUploadTask:0x165ade60> {taskIdentifier:1} data:0'當我嘗試附加數據時,會崩潰我的應用程序 – user1284151

+0

如果您在某處(例如GitHub或其他地方)上傳工作演示,我很高興看一看。 – Rob

0

對於測試後臺會話代碼,建議在真實設備上測試。當編寫使用NSURLSession的背景會話支持的應用程序,這是容易混淆的發展過程中的三個非顯而易見的假象:

  • 當您從Xcode中的應用程序時,Xcode安裝應用程序在新的容器,這意味着您的應用的路徑發生變化。這可能會混淆NSURLSession的後臺會話支持。 注意:此問題已在iOS 9中修復;如果遇到NSURLSession在iOS 9或更高版本中未處理容器路徑更改時出現問題,請提交錯誤。
  • Xcode的調試功能可以防止系統暫停您的應用程序。因此,如果您從Xcode運行您的應用程序,或者在啓動後一段時間附加到該過程,然後將您的應用程序移動到後臺,則應用程序將繼續在系統將其掛起的情況下執行。
  • 同樣,iOS模擬器不能準確地模擬應用程序掛起和恢復;這在過去有效,但在iOS 8或iOS 9模擬器中不起作用。

來源:Apple Developer Forum