Ios WatchKit扩展后台刷新的Apple示例代码

Ios WatchKit扩展后台刷新的Apple示例代码,ios,iphone,swift,apple-watch,Ios,Iphone,Swift,Apple Watch,我已经寻找这个问题的答案很长时间了,所以我想我愿意冒着被否决的风险发布它 基本上,我想让Apple提供的Apple Watch后台刷新示例代码真正起作用(下面的链接和代码) 我已经在模拟器和iPhone6S上试用了Apple Watch Series 2,后台任务从未成功完成到时间更新的程度。我已经尝试将watch应用程序固定到dock上,并且尝试将应用程序保持在前台并发送到后台,无论是在模拟器中还是在实际的手表上。我甚至试着等了将近一年,看看Xcode或Apple Watch是否会收到能让它工

我已经寻找这个问题的答案很长时间了,所以我想我愿意冒着被否决的风险发布它

基本上,我想让Apple提供的Apple Watch后台刷新示例代码真正起作用(下面的链接和代码)

我已经在模拟器和iPhone6S上试用了Apple Watch Series 2,后台任务从未成功完成到时间更新的程度。我已经尝试将watch应用程序固定到dock上,并且尝试将应用程序保持在前台并发送到后台,无论是在模拟器中还是在实际的手表上。我甚至试着等了将近一年,看看Xcode或Apple Watch是否会收到能让它工作的更新

是否有人成功地修改了苹果提供的代码以使其正常工作

您可以在此处下载整个可运行示例项目:

/*
版权(C)2016-2017苹果公司。保留所有权利。
有关此示例的许可信息,请参阅LICENSE.txt
摘要:
主界面控制器。
*/
进口手表套件
进口基金会
类MainInterfaceController:WKInterfaceController、WKExtensionDelegate、URLSessionDownloadDelegate{
//马克:财产
让sampleDownloadURL=URL(字符串:http://devstreaming.apple.com/videos/wwdc/2015/802mpzd3nzovlygpbg/802/802_designing_for_apple_watch.pdf?dl=1")!
@IBOutlet var timeDisplayLabel:WKInterfaceLabel!
私有let日期格式化程序:日期格式化程序={
let formatter=DateFormatter()
formatter.dateStyle=.none
formatter.timeStyle=.long
返回格式化程序
}()
//马克:WKEncontroller
覆盖函数唤醒(withContext:有吗?){
super.awake(withContext:context)
//在此处配置接口对象。
WKExtension.shared().delegate=self
updateDateLabel()
}
//马克:WKExtensionLegate
func句柄(uuBackgroundTasks:Set){
对于任务:背景任务中的WKRefreshBackgroundTask{
打印(“接收到的后台任务:,任务”)
//仅在后台运行时处理这些
if(WKExtension.shared().applicationState==.background){
如果任务为WKApplicationRefreshBackgroundTask{
//此任务在下面完成后,我们的应用程序将在下载会话运行时挂起
打印(“收到应用程序任务,启动URL会话”)
scheduleURLSession()
}
}
如果将urlTask=任务设为?WKURLSessionRefreshBackgroundTask,则为else{
让backgroundConfigObject=URLSessionConfiguration.background(标识符为urlTask.sessionIdentifier)
让backgroundSession=URLSession(配置:backgroundConfigObject,委托:self,委托队列:nil)
打印(“重新加入会议”,背景会议)
}
//确保完成所有任务,即使是你没有处理的任务
task.setTaskCompleted()已完成
}
}
//标记:快照和UI更新
func scheduleshopshot(){
//开火,我们准备好了
让fireDate=Date()
WKExtension.shared().scheduleSnapshotRefresh(withPreferredDate:fireDate,userInfo:nil){中出现错误
if(错误==零){
打印(“已成功计划快照。所有后台工作已完成。”)
}
}
}
func updateDateLabel(){
让currentDate=Date()
timeDisplayLabel.setText(dateFormatter.string(from:currentDate))
}
//标记:URLSession处理
func urlSession(session:urlSession,downloadTask:URLSessionDownloadTask,didFinishDownloadingTo位置:URL){
打印(“NSURLSession已完成到url:,位置”)
updateDateLabel()
scheduleSnapshot()
}
func scheduleURLSession(){
让backgroundConfigObject=URLSessionConfiguration.background(带有标识符:nsuid().uuidString)
backgroundConfigObject.sessionSendsLaunchEvents=true
让backgroundSession=URLSession(配置:backgroundConfigObject)
让downloadTask=backgroundSession.downloadTask(带:sampleDownloadURL)
downloadTask.resume()
}
//标记:IB操作
@iAction func ScheduleRefreshButtonTapped(){
//20秒后开火
让fireDate=日期(时间间隔自现在起:20.0)
//可选,可在此传递任何符合SecureCoding的数据
让userInfo=[“原因”:“后台更新”]作为NSDictionary
WKExtension.shared().scheduleBackgroundRefresh(使用PreferredDate:fireDate,userInfo:userInfo){(错误)在中
如果(错误==nil){
打印(“已成功安排后台任务,使用crown将应用程序发送到后台,并等待handle:BackgroundTasks启动。”)
}
}
}
}
以下是在模拟器上运行时的输出。在其他配置中运行时的类似输出(但不一定完全相同):

successfully scheduled background task, use the crown to send the app to the background and wait for handle:BackgroundTasks to fire.
received background task:  <WKSnapshotRefreshBackgroundTask: 0x7b019030>
received background task:  <WKApplicationRefreshBackgroundTask: 0x7a711290>
application task received, start URL session
已成功安排后台任务,请使用crown将应用程序发送到后台,并等待启动handle:BackgroundTasks。
收到的后台任务:
收到的后台任务:
收到应用程序任务,启动URL会话

对于任何可能发现这一点的人,我发现有两个问题,都与URLSession调度有关。有了这些变化,我认为苹果的示例代码实际上可以工作,至少在模拟器上是这样

-
sampleDownloadURL
需要是安全的,因此需要一个带有HTTPS的URL。这一个有效:

-在我看来,
URLSession
的委托从未设置为
self
,因此以下更改已修复:

let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil)
以下工作(尽管不太完整)代码非常有用:

编辑:可能出现的另一个问题是任务
let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil)