URLSession.datatask,后台未调用请求块 [英] URLSession.datatask with request block not called in background

查看:236
本文介绍了URLSession.datatask,后台未调用请求块的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

URLSession 数据任务块在应用程序处于后台时未调用,并且在请求时停留在 dataTask

当我打开应用程序时,块被调用。顺便说一句,我正在使用 https 请求。

这是我的代码:

URLSession data task block is not calling when the app is in background and it stuck at dataTask with request.
When I open the app the block gets called. By the way I'm using https request.
This is my code:

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

当应用处于活动状态时,可以正常工作。我的代码有什么问题吗?请指出我

Working perfectly when the app is in active state. Is there anything wrong in my code. please point me

推荐答案

如果您希望在应用程序不再处于前台后进行下载,则必须使用后台会话。背景会话的基本限制在 URL会话编程指南:使用NSURLSession:后台传输注意事项,基本上是:

If you want downloads to progress after your app is no longer in foreground, you have to use background session. The basic constraints of background sessions are outlined in URL Session Programming Guide: Using NSURLSession: Background Transfer Considerations, and are essentially:


  1. 使用基于委托的 URLSession ,背景为 URLSessionConfiguration

仅使用上传和下载任务,没有完成处理程序。

Use upload and download tasks only, with no completion handlers.

实施 application(_:handleEventsForBackgroundURLSession:completionHandler:) app delegate,保存完成处理程序并启动后台会话。

Implement application(_:handleEventsForBackgroundURLSession:completionHandler:) in your app delegate, saving the completion handler and starting your background session.

实施 <$你的 URLSessionDelegate 中的c $ c> urlSessionDidFinishEvents(forBackgroundURLSession:) ,调用保存的完成处理程序让操作系统知道你已完成处理后台请求完成。

Implement urlSessionDidFinishEvents(forBackgroundURLSession:) in your URLSessionDelegate, calling that saved completion handler to let OS know you're done processing the background request completion.

所以,把它拉到一起:

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
}

这篇关于URLSession.datatask,后台未调用请求块的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆