尝试在watchOS中进行后台刷新时,不会调用WKURLSessionRefreshBackgroundTask

时间:2016-12-15 04:22:26

标签: watchkit nsurlsession watch-os watch-os-3 wkrefreshbackgroundtask

我正在处理复杂问题以从Web服务获取计划数据。每20-30分钟(或手动),我正在安排WKRefreshBackgroundTask来执行此操作。

正如Apple建议的那样,我希望操作系统通过后台NSURLSession来处理这些数据的获取。

这是我用来下载我需要的数据的功能:

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()
}

关于此的一些事情:

  1. 我安排时会调用它。我在控制台中看到了它的print语句。
  2. 它与Apple的例子几乎相同。
  3. 我省略了网址。同样的URL在iOS / watchOS应用程序中工作得很好,所以没有任何问题。
  4. 问题是,即使我在任务上调用resume()并允许它在完成时唤醒我的应用程序,但它似乎也没有。

    完成后,它应该回到WKExtensionDelegate处理程序:

    func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)
    

    作为WKURLSessionRefreshBackgroundTask,但事实并非如此。

    我的代码与Apple的示例代码相同,然后创建另一个会话,但通过WKURLSessionRefreshBackgroundTask标识符重新加入。这是设置委托以处理下载数据的位置。检查代码:

    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: Using WKRefreshBackgroundTask to update WatchKit apps in the background

    我的项目中是否有一些我不知道的设置?我将所有这些代码放在watch {3}中的ExtensionDelegate新内容中。我也符合WKExtensionDelegateURLSessionDownloadDelegate

    提前感谢您的帮助!

2 个答案:

答案 0 :(得分:4)

我从来没有让Apple的例子工作,但我确实得到了后台刷新功能。与他们的示例不同,您需要使自己成为会话的代表。因此,请改为创建这样的后台会话:

让backgroundSession = URLSession(配置:backgroundSessionConfig,delegate:self,delegateQueue:nil)

我在这里有详细的代码示例(请参阅问题代码):

WatchOS 3 WKApplicationRefreshBackgroundTask didReceiveChallenge

希望它有所帮助。

答案 1 :(得分:4)

我搞定了!我开始时通过观察WWDC&#39; 16视频/笔记,将它们与Apple的WatchBackgroundRefresh示例进行比较。然后,在浏览Apple Dev论坛时,我找到了this thread,遇到了同样的问题。在那里,一个人,&#34; Daniel Fontes&#34;发布他的食谱&#39;让它工作(注意,不是接受的答案!),并结合视频为我工作。

我为使Apple示例工作做了什么:

  1. 使MainInterfaceController成为URLSessionDelegate
  2. 创建一个本地变量:var savedTask:WKRefreshBackgroundTask?
  3. handle( backgroundTasks:)函数中,将WKURLSessionRefreshBackgroundTask保存到局部变量self.savedTask = task - 不要task.setTaskCompleted()(!!)
  4. urlSession - didFinishDownloading:中,在您阅读收到的数据后,将已保存的任务设置为已完成:self.savedTask?.setTaskCompleted()
  5. 确保您访问的资源是https://,否则添加&#34;应用传输安全设置&#34;到您的Info.plist文件。
  6. 希望这可以提供帮助!

    PS。这适用于模拟器(xcode 8.3.3,watchOS 3.2)