繁体   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