9

我正在研究从 Web 服务获取预定数据的复杂性。每 20-30 分钟(或手动),我安排一个 WKRefreshBackgroundTask 来执行此操作。

正如 Apple 所建议的,我希望操作系统通过 background 处理这些数据的获取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. 当我安排它时,它会被调用。我在控制台中看到了它的打印语句。
  2. 这与苹果的例子几乎相同。
  3. 我省略了网址。相同的 URL 在 iOS/watchOS 应用程序中运行良好,因此没有任何问题。

问题是,即使我正在调用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

我的项目中是否有一些我缺少的设置?我将所有这些代码放在ExtensionDelegatewatchOS 3 中的新代码中。我也符合WKExtensionDelegateURLSessionDownloadDelegate

提前感谢您的帮助!

4

2 回答 2

5

我让它工作了!我开始大量查看 WWDC'16 视频/笔记,并将它们与 Apple 的WatchBackgroundRefresh示例进行比较。然后,在浏览 Apple Dev 论坛时,我发现了这个线程,与我们遇到的问题相同。在那里,一个名叫“Daniel Fontes”的人发布了他的“食谱”,让它发挥作用(注意,不是公认的答案!),结合视频对我有用。

我为使 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://,否则将“应用程序传输安全设置”添加到您的 Info.plist 文件中。

希望这可以帮助!

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

于 2017-07-16T11:16:12.147 回答
4

我从来没有让苹果的例子工作,但我确实让后台刷新工作。与他们的示例不同,您需要让自己成为会话的代表。所以像这样创建你的后台会话:

让 backgroundSession = URLSession(配置:backgroundSessionConfig,委托:自我,委托队列:无)

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

WatchOS 3 WKApplicationRefreshBackgroundTask didReceiveChallenge

希望能帮助到你。

于 2017-02-21T21:34:04.600 回答