【问题标题】:Is it a proper way to use background task for additional HTTP request after background download/upload finishes?后台下载/上传完成后使用后台任务进行额外 HTTP 请求的正确方法吗?
【发布时间】:2018-12-27 15:36:38
【问题描述】:

我想在后台下载/上传后发出额外的 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) {

}

问题

在后台传输后进行一些工作是正确的方法吗?

【问题讨论】:

    标签: ios swift nsurlsession nsurlsessionconfiguration


    【解决方案1】:

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

    【讨论】:

    • 感谢您的回答。我应该在请求完成后还是在恢复请求后从 handleEventsForBackgroundURLSession 调用完成块?我应该将此请求包装到后台任务中吗?
    • 在新任务上调用resume 之后。你不想让操作系统等待很长时间——只要足够长的时间来安排事情和做你必须做的任何管理工作——否则操作系统会再次开始惩罚你的日程安排。
    【解决方案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()
                })
            }
        }
    }
    

    我希望这会有所帮助。

    【讨论】:

      猜你喜欢
      • 2015-07-10
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多