在后台下载/上传完成之后,是否是将后台任务用于其他HTTP请求的正确方法?

时间:2018-12-27 15:36:39

标签: ios swift nsurlsession nsurlsessionconfiguration

我想在后台下载/上传后再发出一个HTTP请求,以确认应用程序已完成下载/上传。让我给你看一个简单的例子。

首先,我们需要创建下载/上传任务。

let configuration = URLSessionConfiguration.background(withIdentifier: UUID().uuidString)
configuration.sessionSendsLaunchEvents = true
configuration.isDiscretionary = true
let session = URLSession(configuration: configuration, delegate: self, delegateQueue: nil)
session.downloadTask(with: largeFileURL).resume()

然后,我们需要在下载/上传完成后触发一些其他请求。为了防止应用程序被暂停,我正在使用后台任务。

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {

    backgroundTaskIdentifier = UIApplication.shared.beginBackgroundTask(expirationHandler: { [weak self] in
        finishBackgroundTask()
    })

    let task = URLSession.shared.dataTask(with: someURL) { data, response, error in
        // Process response.
        finishBackgroundTask()
    }
    task.resume()    
}

private func finishBackgroundTask() {
    UIApplication.shared.endBackgroundTask(backgroundTaskIdentifier)
    backgroundTaskIdentifier = .invalid
}

最后一件事是实现应用程序委托方法:

func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {

}

问题

在后台传输后进行某些工作是否正确?

2 个答案:

答案 0 :(得分:3)

如果有内存,最好的方法是在调用完成块之前启动新请求。但是请注意,无论您怎么做,如果您反复发出简短请求,则操作系统将迅速增加后台下载完成与您的应用在后台重新启动以处理会话事件之间的延迟。 >

答案 1 :(得分:2)

我建议在您的AppDelegate中创建一个completionHandler

var backgroundSessionCompletionHandler: (() -> Void)?

然后在handleEventsForBackgroundURLSession UIApplicationDelegate的方法中,您定义完成处理程序

func application(_ application: UIApplication, handleEventsForBackgroundURLSession 
identifier: String, completionHandler: @escaping () -> Void) {
    backgroundSessionCompletionHandler = {
        // Execute your additional HTTP request
    }
}

最后一步是下载完成后调用此完成处理程序

func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
    if let appDelegate = UIApplication.shared.delegate as? AppDelegate {
        if let completionHandler = appDelegate.backgroundSessionCompletionHandler {
            appDelegate.backgroundSessionCompletionHandler = nil
            DispatchQueue.main.async(execute: {
                completionHandler()
            })
        }
    }
}

我希望这会有所帮助。