URLSession
数据任务 block 在应用程序处于后台时未调用,它停留在 dataTask
请求。
当我打开应用程序时, block 被调用。顺便说一下,我正在使用 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()
当应用程序处于事件状态时完美运行。我的代码有什么问题吗?请指点我
最佳答案
如果您希望在您的应用程序不再处于前台后继续下载,您必须使用后台 session 。 Downloading Files in Background 中概述了后台 session 的基本限制。 , 本质上是:
使用基于委托(delegate)的
URLSession
和后台URLSessionConfiguration
。仅使用上传和下载任务,没有完成处理程序。
在 iOS 中,实现
application(_:handleEventsForBackgroundURLSession:completionHandler:)
应用程序委托(delegate),保存完成处理程序并启动后台 session 。实现
urlSessionDidFinishEvents(forBackgroundURLSession:)
在您的URLSessionDelegate
中,调用保存的完成处理程序让操作系统知道您已完成后台请求完成处理。
所以,把它们放在一起:
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 应用程序委托(delegate)会执行以下操作:
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
BackgroundSession.shared.savedCompletionHandler = completionHandler
}
关于ios - 带有未在后台调用的请求 block 的 URLSession.datatask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44128358/