簡體   English   中英

帶有請求塊的 URLSession.datatask 未在后台調用

[英]URLSession.datatask with request block not called in background

URLSession數據任務塊在應用程序處於后台時不會調用,並且它在請求時停留在dataTask
當我打開應用程序時,塊被調用。 順便說一下,我正在使用https請求。
這是我的代碼:

    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()

當應用程序處於活動狀態時完美運行。 我的代碼有什么問題嗎。 請指點我

如果您希望在您的應用程序不再處於前台后繼續下載,您必須使用后台會話。 在后台下載文件中概述了后台會話的基本約束,本質上是:

  1. 將基於委托的URLSession與背景URLSessionConfiguration

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

  3. 在 iOS 中,實現application(_:handleEventsForBackgroundURLSession:completionHandler:)應用程序委托,保存完成處理程序並啟動后台會話。

    在您的URLSessionDelegate實現urlSessionDidFinishEvents(forBackgroundURLSession:) ,調用保存的完成處理程序以讓操作系統知道您已完成處理后台請求完成。

所以,把它放在一起:

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!

    #if !os(macOS)
    var savedCompletionHandler: (() -> Void)?
    #endif
    
    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 {
    #if !os(macOS)
    func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
        DispatchQueue.main.async {
            self.savedCompletionHandler?()
            self.savedCompletionHandler = nil
        }
    }
    #endif
}

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)")
        }
    }
}

iOS 應用程序委托執行以下操作:

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

您需要一個后台會話。 根據 Apple 的文檔, URLSessionDataTask 不支持后台下載。

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

按照這個鏈接

或者干脆啟動一個BackgroundTask

func send(...) {
  let backgroundTaskID = UIApplication.shared.beginBackgroundTask(expirationHandler: nil)
  let session = URLSession(configuration: .default)

  // ... after all the main logic, when you finish:
  DispatchQueue.main.async {
    completion(result)
    UIApplication.shared.endBackgroundTask(backgroundTaskID)
  }
}
  [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];

// 如圖所示應用

/*********************/ 在此處輸入圖片說明

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM