【问题标题】:WatchOS 3 WKApplicationRefreshBackgroundTask didReceiveChallengeWatchOS 3 WKApplicationRefreshBackgroundTask didReceiveChallenge
【发布时间】:2016-11-03 14:56:54
【问题描述】:

我终于(忽略了在“收到应用程序任务,启动 URL 会话”之后从未见过的示例代码)设法让我的 WatchOS3 代码启动后台 URL 会话任务,如下所示:

 func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {

    for task in backgroundTasks {
        if let refreshTask = task as? WKApplicationRefreshBackgroundTask {
            // this task is completed below, our app will then suspend while the download session runs
            print("application task received, start URL session")

            let request = self.getRequestForRefresh()
            let backgroundConfig = URLSessionConfiguration.background(withIdentifier: NSUUID().uuidString)
            backgroundConfig.sessionSendsLaunchEvents = true
            backgroundConfig.httpAdditionalHeaders = ["Accept":"application/json"]
            let urlSession = URLSession(configuration: backgroundConfig, delegate: self, delegateQueue: nil)
            let downloadTask = urlSession.downloadTask(with: request)

            print("Dispatching data task at \(self.getTimestamp())")
            downloadTask.resume()

            self.scheduleNextBackgroundRefresh(refreshDate: self.getNextPreferredRefreshDate())
            refreshTask.setTaskCompleted()
        }
        else if let urlTask = task as? WKURLSessionRefreshBackgroundTask {
            //awakened because background url task has completed
            let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: urlTask.sessionIdentifier)
            self.backgroundUrlSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) //set to nil in task:didCompleteWithError: delegate method

            print("Rejoining session ", self.backgroundUrlSession as Any)
            self.pendingBackgroundURLTask = urlTask //Saved for .setTaskComplete() in downloadTask:didFinishDownloadingTo location: (or if error non nil in task:didCompleteWithError:) 

        } else {
            //else different task, not handling but must Complete all tasks (snapshot tasks hit this logic)
            task.setTaskCompleted()
        }
    }
}

但是,我现在看到的问题是我的委托方法 urlSession:task:didReceiveChallenge: 永远不会被击中,所以我无法完成下载。 (我还添加了会话级别的 urlSession:didReceiveChallenge: 委托方法,它也没有被命中)。

相反,我立即点击了出现错误的 task:didCompleteWithError: 委托方法:

“此服务器的证书无效。您可能正在连接到一个伪装成...的服务器,这可能会使您的机密信息面临风险。”

是否有人获得了后台监视更新来满足在后台 URL 会话期间点击 didReceiveChallenge 方法的额外要求?

感谢您提供的任何帮助或建议。

【问题讨论】:

  • 顺便说一句,此代码适用于我没有收到无效证书错误的生产框上的后台刷新。 (Xcode 8.1 和 WatchOS3)
  • 这真的适合你吗?下载完成后您会收到 WKURLSessionRefreshBackgroundTask 吗?
  • 是的,这对我们有用。确保在创建会话时将自己设置为会话的代表。另请注意,WKURLSessionRefreshBackgroundTask 块是必要的(即使您可能无法使用断点命中它)。确保不要完成该块中的任务,而是坚持并在您的 didFinishDownloadingTo 或 didCompleteWithError 委托方法的逻辑之后完成它。
  • 通过在 URLSession 上设置委托,我也可以像在您的示例中一样进行后台刷新。 didFinishDownloadingToURL 委托方法被调用,一切似乎都正常。但这不是它应该工作的方式,我宁愿以正确的方式去做,只要它有效......
  • 我也对这个事实感到非常沮丧。我已经习惯了 Apple 的代码示例的工作方式。但是当我下载他们的后台刷新代码示例并且从未在我的手表上看到它工作时,我最终不得不放弃并继续使用有效的方法。我根据 Apple 论坛中其他沮丧的开发人员的 cmets 和反复试验拼凑了这个实现。 (无论您身在何处,都感谢 Daniel Fontes)。我只能说它有效。我不知道它“应该”如何工作。但我很高兴我的例子帮助了你。 :-) forums.developer.apple.com/message/156604#170909

标签: ios swift watchos-3 wkrefreshbackgroundtask


【解决方案1】:

事实证明,服务器证书错误实际上是由于我们的测试环境中的一种罕见情况造成的。在后端人员为我们解决该问题后,此代码在我们的生产和测试环境中都运行良好。

我从来没有打过urlSession:task:didReceiveChallenge:,但事实证明我不需要。

做了一个不相关的小改动:
在没有打印/断点的情况下,我有时会在点击 downloadTask:didFinishDownloadingTo location: 之前像毫秒一样点击 task:didCompleteWithError Error:

所以我改为设置 self.pendingBackgroundURLTask 在downloadTask:didFinishDownloadingTo location: 中完成。如果错误!= nil,我只在task:didCompleteWithError Error: 中设置完成。

func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {

    //Complete task only if error, if no error it will be completed when download completes (avoiding race condition)
    if error != nil {
        self.completePendingBackgroundTask()
    }

}

func completePendingBackgroundTask()
{
    //Release the session
    self.backgroundUrlSession = nil

    //Complete the task
    self.pendingBackgroundURLTask?.setTaskCompleted()
    self.pendingBackgroundURLTask = nil
}

希望其他人会觉得这很有帮助。

【讨论】:

  • 所以你从来不用invalidateAndCancel()
  • 不,我没有,但在将 backgroundUrlSession 设置为 nil 之前添加这绝对是一件好事。
  • 谢谢!我也很快完成了任务,我现在在 URLSessionDidFinishEventsForBackgroundURLSession 委托方法中完成了这项任务。它被记录为意味着“所有消息都已传递”,尽管仅参考 iOS。在 Fontes 的回答中也提到了。这似乎现在也可以在模拟器中使用。
  • 这行得通,但奇怪的是为什么不调用 WKURLSessionRefreshBackgroundTask
猜你喜欢
  • 1970-01-01
  • 2017-08-04
  • 2016-12-17
  • 1970-01-01
  • 2016-11-25
  • 2023-03-29
  • 2016-12-20
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多