【问题标题】:Update data with URLSession in Background Fetch在后台获取中使用 URLSession 更新数据
【发布时间】:2017-08-11 16:56:16
【问题描述】:

我正在开发一个应用程序,我需要每天更新我的应用程序中的数据。我决定使用后台获取。我正在从 API 下载数据,所以我使用的是 URLSession。由于performFetchWithCompletionHandler 中不允许使用完成处理程序,因此我为此目的使用委托。但我的问题是,当我的应用程序未运行时尝试更新数据时,不会调用函数didRecieve data。我是在做错什么,还是应该每天使用其他东西从 API 更新我的数据?

我的代码如下:

func createTask(url: String, id: String){
    let accessKey = UserDataService().getCurrentUser().accessToken

    let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: id + UUID().uuidString)
    let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil)


    var request = URLRequest(url: URL(string: url)!)
    request.setValue("Bearer \(accessKey!)", forHTTPHeaderField: "Authorization")
    request.addValue("application/json", forHTTPHeaderField: "Content-Type")
    request.httpMethod = "GET"

    let task = backgroundSession.dataTask(with: request)

    task.resume()

    print("task resumed")
}

这个函数在performFetchWithCompletionHandler内部被调用并创建新的dataTask,但didRecieve data没有被调用。

我也尝试在 performFetchWithCompletionHandler 中添加此代码

print("BG FETCH")

let url = "secret url"

var request = URLRequest(url: URL(string: url)!)
request.setValue("SOME KEY", forHTTPHeaderField: "Authorization")
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
request.httpMethod = "GET"

URLSession.shared.dataTask(with: request, completionHandler: { (data, response, error) in
    print("DATA",data)
    completionHandler(.newData)
}).resume()

感谢您的任何建议!

【问题讨论】:

  • 我不确定,但非常怀疑您是否可以从 backgroundState 启动 backgroundSession。如果它已经在前台启动,您应该只能继续它。想象一下,如果应用程序能够进行长时间的后台下载并且用户永远不知道并且意识到 5Gb 是使用他的蜂窝数据下载的,将会发生什么。他们会立即删除您的应用!
  • @Honey 那你有什么建议。我的应用依赖于更新。
  • 我没怎么用过后台应用刷新,但是看了下,没有看到任何提及:“performFetchWithCompletionHandler 中不允许完成处理程序”
  • @Honey 由this 和邓肯的回答确认
  • @Honey 我正在使用背景会话。无论如何,您是否建议任何其他方式来更新我的应用程序中的数据以在用户打开应用程序时准备好?

标签: ios swift nsurlsession background-fetch urlsession


【解决方案1】:

我记得后台只支持上传下载,不支持数据任务。

您是对的,您不能使用带有完成处理程序的调用。您必须提供委托。

在 Xcode 中搜索字符串“在后台下载内容”。有相当广泛的文档。

它的要点是系统将在需要时重新启动您的应用程序并调用其application:handleEventsForBackgroundURLSession:completionHandler: 方法。

您必须在 info.plist 文件中设置适当的应用权限。 (我不记得您是否必须征求用户的许可才能进行后台下载。请参阅文档。)

以下是 Apple Xcode 文档的第一部分信息:

在后台下载内容

下载文件时,应用程序应使用 NSURLSession 对象 开始下载,以便系统可以控制 下载过程,以防应用程序被暂停或终止。当你 为后台传输配置一个 NSURLSession 对象,系统 在单独的流程中管理这些转移并报告状态 以通常的方式添加到您的应用程序。如果您的应用程序在 转移正在进行中,系统继续在 后台并在传输时启动您的应用程序(视情况而定) 完成或当一项或多项任务需要您的应用注意时。

要支持后台传输,你必须配置你的 NSURLSession 适当地反对​​。要配置会话,您必须首先创建 一个 NSURLSessionConfiguration 对象并将几个属性设置为 适当的值。然后将该配置对象传递给 创建您的 NSURLSession 时的适当初始化方法 会话。

创建配置对象的过程支持 后台下载如下:

使用 backgroundSessionConfigurationWithIdentifier:方法 NSURLSession 配置。设置配置对象的值 sessionSendsLaunchEvents 属性为 YES。如果您的应用开始传输 当它在前台时,建议您同时设置 配置对象的任意属性为 YES。配置 配置对象的任何其他属性(视情况而定)。采用 配置对象来创建你的 NSURLSession 对象。一次 配置后,您的 NSURLSession 对象将无缝地移交上传和 在适当的时候将任务下载到系统。如果任务完成 当您的应用仍在运行时(在前台或 背景),会话对象以通常的方式通知其委托 方式。如果任务尚未完成且系统终止您的 应用程序,系统自动继续管理应用程序中的任务 背景。如果用户终止您的应用程序,系统将取消任何 待处理的任务。

当与后台会话关联的所有任务都 完成,系统重新启动一个终止的应用程序(假设 sessionSendsLaunchEvents 属性设置为 YES 并且用户做了 不强制退出应用程序)并调用应用程序委托的 应用程序:handleEventsForBackgroundURLSession:completionHandler: 方法。 (系统也可能会重新启动应用程序来处理身份验证 需要您的应用程序的挑战或其他与任务相关的事件 注意。)在该委托方法的实现中,使用 提供标识符来创建一个新的 NSURLSessionConfiguration 和 NSURLSession 对象与之前的配置相同。系统 将您的新会话对象重新连接到以前的任务和报告 将它们的状态传递给会话对象的委托。

【讨论】:

  • 好的,我确实知道你在这里写的确切内容。后台只支持上传下载,不支持数据任务。您不能使用带有完成处理程序的调用。你必须提供一个代表。但是,当我使用后台获取调试代码时,我确实创建了一个 dataTaskWithRequest,最有趣的部分是我确实使用了完成处理程序的调用,并且调试器确实在我放置在回调函数中的断点处停止。该项目是用 Swift 2.3 编写的,是否可以与 Swift 版本相关?
  • “在后台”这个词有几种不同的用法。这可能意味着您的应用程序仍在运行,但另一个应用程序位于最前面。数据任务将继续运行。如果您的应用程序被暂停(仍在内存中但没有获得 CPU 时间)那么我相信数据任务也将被暂停,并且当您的应用程序再次获得时间时将继续。 Apple 正在使用的“后台下载”的另一种含义是系统接管下载管理,即使您的应用程序被终止,它也会继续运行。为此,您需要使用后台任务和委托。
  • 如果您能与我分享如何在操作系统接管的地方模拟 Apple 正在使用的那个,我将不胜感激,即使应用程序在模拟器或设备上被终止。
  • 我没有任何非专有代码来展示如何做到这一点。但是,文档非常清楚,并拼写了所需的步骤。 (我引用了上面最重要的部分。)
猜你喜欢
  • 2021-04-04
  • 2020-07-14
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2017-05-20
  • 1970-01-01
  • 2023-02-07
  • 2020-06-26
相关资源
最近更新 更多