2017-05-23 18 views
2

URLSession數據任務塊在應用程序處於後臺時未調用,並且它在請求中停留在dataTask
當我打開應用程序塊被調用。順便說一句,我正在使用https請求。
這是我的代碼:帶請求塊的URLSession.datatask在後臺未調用

let request = NSMutableURLRequest(url: URL(string: url as String)!, 

             cachePolicy: .reloadIgnoringCacheData, 

             timeoutInterval:20) 

    request.httpMethod = method as String 

    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 

    let session = URLSession.shared 

    let data = params.data(using: String.Encoding.utf8.rawValue) 

    request.httpBody = data 

    session.dataTask(with: request as URLRequest,completionHandler: 

     {(data, response, error) -> Void in 

     if error == nil 

      { 

       do { 

        let result = try JSONSerialization.jsonObject(with: data!, options: 

         JSONSerialization.ReadingOptions.mutableContainers) 

        print(result) 

        completionHandler(result as AnyObject?,nil) 

       } 

       catch let JSONError as NSError{ 

        completionHandler(nil,JSONError.localizedDescription as NSString?) 

       } 

      } 

      else{ 

       completionHandler(nil,error!.localizedDescription as NSString?)      

      }     

    }).resume() 

完美的工作時,應用程序處於活動狀態。我的代碼有什麼問題嗎?請指點我

+0

沒有關係,但爲什麼你傳遞'。 mutableContainers',但將結果分配給不可變常量?並且不要在Swift中使用'NSURLRequest'和'NSString',使用本地結構。最後,'String.Encoding.utf8.rawValue'可以寫成'.utf8',這是更少的代碼鍵入(或粘貼)。 – vadian

+1

'會話'是後臺會話嗎?如果是這樣,請執行基於委託的下載任務,而不是數據任務。請參閱[後臺傳輸注意事項](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/URLLoadingSystem/Articles/UsingNSURLSession.html#//apple_ref/doc/uid/TP40013509-SW44)。 – Rob

+0

這意味着我可以使用下載任務eventhough沒有什麼可下載的。 –

回答

1

如果您希望在應用程序不再處於前景之後進行下載,則必須使用後臺會話。背景會議的基本約束URL Session Programming Guide: Using NSURLSession: Background Transfer Considerations概述,並且基本上是:

  1. 以代理人爲基礎URLSession背景URLSessionConfiguration

  2. 只使用上傳和下載任務,沒有完成處理程序。

  3. 在您的應用程序委託中實現application(_:handleEventsForBackgroundURLSession:completionHandler:),保存完成處理程序並開始後臺會話。

    在您的URLSessionDelegate中執行urlSessionDidFinishEvents(forBackgroundURLSession:),調用保存的完成處理程序讓O​​S知道您已完成處理後臺請求完成。

所以,拉一起:

func startRequest(for urlString: String, method: String, parameters: String) { 
    let url = URL(string: urlString)! 
    var request = URLRequest(url: url, cachePolicy: .reloadIgnoringCacheData, timeoutInterval: 20) 
    request.httpMethod = method 
    request.setValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type") 
    request.httpBody = parameters.data(using: .utf8) 
    BackgroundSession.shared.start(request) 
} 

class BackgroundSession: NSObject { 
    static let shared = BackgroundSession() 

    static let identifier = "com.domain.app.bg" 

    private var session: URLSession! 

    var savedCompletionHandler: (() -> Void)? 

    private override init() { 
     super.init() 

     let configuration = URLSessionConfiguration.background(withIdentifier: BackgroundSession.identifier) 
     session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil) 
    } 

    func start(_ request: URLRequest) { 
     session.downloadTask(with: request).resume() 
    } 
} 

extension BackgroundSession: URLSessionDelegate { 
    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) { 
     DispatchQueue.main.async { 
      self.savedCompletionHandler?() 
      self.savedCompletionHandler = nil 
     } 
    } 
} 

extension BackgroundSession: URLSessionTaskDelegate { 
    func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) { 
     if let error = error { 
      // handle failure here 
      print("\(error.localizedDescription)") 
     } 
    } 
} 

extension BackgroundSession: URLSessionDownloadDelegate { 
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) { 
     do { 
      let data = try Data(contentsOf: location) 
      let json = try JSONSerialization.jsonObject(with: data) 

      print("\(json)") 
      // do something with json 
     } catch { 
      print("\(error.localizedDescription)") 
     } 
    } 
} 

和應用程序委託所做的:

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping() -> Void) { 
    BackgroundSession.shared.savedCompletionHandler = completionHandler 
} 
+0

**** ing救了我的生命。謝謝@Rob –

+0

我剛測試過它,工作完美。萬分感謝兄弟 –

0

你需要一個後臺會話。根據Apple文檔的URLSessionDataTask不支持後臺下載。

創建一個URLSessionDownloadTask並使用它應該工作的委託方法。

按照此link

+0

可以給我鏈接相關的或任何示例代碼。 bcoz im a no no –

+0

添加了它應該讓你通過的鏈接。 – rameez

0
[URLSessionDownloadTask setDownloadTaskDidWriteDataBlock:^(NSURLSession *session, NSURLSessionDownloadTask *downloadTask, int64_t bytesWritten, int64_t totalBytesWritten, int64_t totalBytesExpectedToWrite) { 
       CGFloat percentDone = (double)(totalBytesWritten)/(double)totalBytesExpectedToWrite; 
       [SVProgressHUD showWithStatus:[NSString stringWithFormat:@"%.2f%%",percentDone*100]]; 

      }]; 

     [downloadTask resume]; 

//應用如上圖

/*********************/enter image description here

+0

做到了。我點擊服務器時,當我得到推送通知時,應用程序在後臺 –

+0

不關心通知,仍然檢查背景獲取 – ajjjjjjjj

+0

後臺提取啓用 –