xcode 带有请求块的 URLSession.datatask 未在后台调用
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/44128358/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
URLSession.datatask with request block not called in background
提问by Test Test
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:
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()
Working perfectly when the app is in active state. Is there anything wrong in my code. please point me
当应用程序处于活动状态时完美运行。我的代码有什么问题吗。请指点我
回答by Rob
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 Downloading Files in Background, and are essentially:
如果您希望在您的应用程序不再处于前台后继续下载,您必须使用后台会话。在后台下载文件中概述了后台会话的基本约束,本质上是:
Use delegate-based
URLSession
with backgroundURLSessionConfiguration
.Use upload and download tasks only, with no completion handlers.
In iOS, Implement
application(_:handleEventsForBackgroundURLSession:completionHandler:)
app delegate, saving the completion handler and starting your background session.Implement
urlSessionDidFinishEvents(forBackgroundURLSession:)
in yourURLSessionDelegate
, calling that saved completion handler to let OS know you're done processing the background request completion.
使用基于委托的
URLSession
背景URLSessionConfiguration
。仅使用上传和下载任务,没有完成处理程序。
在 iOS 中,实现
application(_:handleEventsForBackgroundURLSession:completionHandler:)
应用程序委托,保存完成处理程序并启动后台会话。urlSessionDidFinishEvents(forBackgroundURLSession:)
在您的 中实现URLSessionDelegate
,调用保存的完成处理程序,让操作系统知道您已完成后台请求完成处理。
So, pulling that together:
所以,把它放在一起:
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)
}
Where
在哪里
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)")
}
}
}
And the iOS app delegate does:
iOS 应用程序委托执行以下操作:
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
BackgroundSession.shared.savedCompletionHandler = completionHandler
}
回答by rameez
You need a background session. The URLSessionDataTask which as per Apple's documentation doesn't support background downloads.
您需要一个后台会话。根据 Apple 的文档, URLSessionDataTask 不支持后台下载。
Create a URLSessionDownloadTask
and use its delegate method it should work.
创建一个URLSessionDownloadTask
并使用它应该工作的委托方法。
Follow this link
按照这个链接
回答by Ajjjjjjjj
[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];
// Apply as shown in picture
// 如图所示应用