URLSession.datatask,后台没有调用请求块

时间:2017-05-23 07:27:21

标签: ios swift xcode xcode8 nsurlsession

当应用程序处于后台时,

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

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

4 个答案:

答案 0 :(得分:18)

如果您希望在应用不再位于前台后进行下载,则必须使用后台会话。背景会话的基本限制在URL Session Programming Guide: Using NSURLSession: Background Transfer Considerations中列出,基本上是:

  1. 使用基于代理的URLSession与背景URLSessionConfiguration

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

  3. 在您的app委托中实施application(_:handleEventsForBackgroundURLSession:completionHandler:),保存完成处理程序并启动后台会话。

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

  4. 所以,把它拉到一起:

    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
    }
    

答案 1 :(得分:0)

您需要一个后台会话。根据Apple的文档,URLSessionDataTask不支持后台下载。

创建一个URLSessionDownloadTask并使用它应该有效的委托方法。

关注此link

答案 2 :(得分:0)

或者直接启动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)
  }
}

答案 3 :(得分:-1)

  [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