问题描述
我正在研究一种复杂性,以从Web服务获取计划的数据.每隔20-30分钟(或手动),我将安排WKRefreshBackgroundTask来执行此操作.
I'm working on a complication to get scheduled data from a web service. Every 20-30 minutes (or manually), I am scheduling a WKRefreshBackgroundTask to do this.
正如Apple所建议的,我希望操作系统通过后台NSURLSession
处理此数据的获取.
As suggested by Apple, I want the OS to handle the fetching of this data via a background NSURLSession
.
这是我用来下载所需数据的功能:
This is the function I use to download the data I need:
func scheduleURLSession()
{
print("\nScheduling URL Session...")
let backgroundSessionConfig:URLSessionConfiguration = URLSessionConfiguration.background(withIdentifier: NSUUID().uuidString)
backgroundSessionConfig.sessionSendsLaunchEvents = true
let backgroundSession = URLSession(configuration: backgroundSessionConfig)
let downloadTask = backgroundSession.downloadTask(with: URL(string: "https://www.myserver.com/somedata")!)
downloadTask.resume()
}
关于此的一些事情:
- 我安排它时确实会调用它.我在控制台中看到了它的打印语句.
- 这几乎与苹果公司的例子相同.
- 我已经省略了网址.相同的URL在iOS/watchOS应用程序中也可以正常工作,因此没有任何问题.
问题是,即使我在任务上调用resume()
并允许它在完成时唤醒我的应用程序,它似乎也没有执行任何操作.
The problem is, even though I am calling resume()
on the task and allowing it to wake my app when it is complete, it doesn't seem to do either.
完成后,它应该返回到WKExtensionDelegate处理程序:
When it completes, it should be coming back to a WKExtensionDelegate handler:
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)
作为WKURLSessionRefreshBackgroundTask
,但不是.
我的代码与Apple的示例代码相同,然后创建另一个会话,但通过WKURLSessionRefreshBackgroundTask
的标识符重新加入该会话.在此处设置委托以便处理下载的数据.检查代码:
My code, identical to Apple's sample code, then creates another session but rejoins it via the WKURLSessionRefreshBackgroundTask
's identifier. This is where the delegate is set in order to process the downloaded data. Check the code:
func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
for task in backgroundTasks {
switch task {
case let backgroundTask as WKApplicationRefreshBackgroundTask:
print("\nWatchKit - WKApplicationRefreshBackgroundTask")
// self.updateComplicationDataArrivalTimes(backgroundTask)
self.scheduleURLSession()
backgroundTask.setTaskCompleted()
case let snapshotTask as WKSnapshotRefreshBackgroundTask:
// Snapshot tasks have a unique completion call, make sure to set your expiration date
print("\nWatchKit - WKSnapshotRefreshBackgroundTask")
snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil)
case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask:
print("\nWatchKit - WKWatchConnectivityRefreshBackgroundTask")
connectivityTask.setTaskCompleted()
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
print("\nWatchKit - WKURLSessionRefreshBackgroundTask")
let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: urlSessionTask.sessionIdentifier)
let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil)
print("Rejoining session ", backgroundSession)
urlSessionTask.setTaskCompleted()
default:
// make sure to complete unhandled task types
task.setTaskCompleted()
}
}
}
但是,它似乎再也不会回来了.尽管代码与该项目的Apple示例代码相同,但我似乎无法弄清楚为什么该方法有效: WatchBackgroundRefresh:使用WKRefreshBackgroundTask在后台更新WatchKit应用.
But again, it doesn't seem to ever come back. I can't seem to figure out why this is working despite the code is identical to Apple's sample code for this project: WatchBackgroundRefresh: Using WKRefreshBackgroundTask to update WatchKit apps in the background.
我的项目中是否缺少某些设置?我将所有这些代码放入watchOS 3中的ExtensionDelegate
中.我也符合WKExtensionDelegate
和URLSessionDownloadDelegate
.
Is there some setting in my project that I am missing? I am putting all this code in the ExtensionDelegate
, new in watchOS 3. I am also conforming to WKExtensionDelegate
and URLSessionDownloadDelegate
.
谢谢您的帮助!
推荐答案
我成功了!我从看WWDC'16的视频/笔记开始,将它们与 WatchBackgroundRefresh (来自Apple的示例).然后,在浏览Apple Dev论坛时,我发现此线程,存在相同的问题我们遇到.在那里,一个叫"Daniel Fontes"的人发布了他的食谱",以使其起作用(注意,不是公认的答案!),并且结合了视频对我有用.
I got it working! I started out by looking a lot at the WWDC'16 videoes/notes, comparing them to the WatchBackgroundRefresh example from Apple. Then, while browsing the Apple Dev forums, I found this thread, with the same problem we encountered. There, a guy, "Daniel Fontes" posts his 'recipe' for getting it to work (note, not the accepted answer!), and that combined with the videos worked for me.
我为使Apple示例工作而做的事情:
What I did to make the Apple example work:
- 使MainInterfaceController成为URLSessionDelegate
- 创建局部变量:
var savedTask:WKRefreshBackgroundTask?
- 在
handle( backgroundTasks:)
函数中,将WKURLSessionRefreshBackgroundTask
保存到局部变量self.savedTask = task
-不要task.setTaskCompleted()(!!) - 在
urlSession - didFinishDownloading:
中,将已保存的任务设置为已完成:self.savedTask?.setTaskCompleted()
在读取接收到的数据之后. - 确保您正在访问的资源为https://,否则将应用程序传输安全设置"添加到您的Info.plist文件中.
- Make the MainInterfaceController an URLSessionDelegate
- Create a local variable:
var savedTask:WKRefreshBackgroundTask?
- In the
handle( backgroundTasks:)
function, save theWKURLSessionRefreshBackgroundTask
to the local variableself.savedTask = task
- do not task.setTaskCompleted() (!!) - In the
urlSession - didFinishDownloading:
, set the saved task to completed:self.savedTask?.setTaskCompleted()
after you've read the data received. - Ensure that the resource you are accessing is https://, otherwise add the "App Transport Security Settings" to your Info.plist file.
希望这会有所帮助!
ps.这可以在模拟器中使用(xcode 8.3.3,watchOS 3.2)
ps. this works in the simnulator (xcode 8.3.3, watchOS 3.2)
这篇关于尝试在watchOS中进行后台刷新时未调用WKURLSessionRefreshBackgroundTask的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!