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

标签 watchkit nsurlsession watchos watchos-3 wkrefreshbackgroundtask

我正在研究一种复杂的方法,以从网络服务获取预定数据。每隔 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. 当我安排它时,它确实会被调用。我在控制台中看到了它的打印语句。
  2. 它与 Apple 的示例几乎相同。
  3. 我省略了网址。同样的 URL 在 iOS/watchOS 应用程序中工作得很好,所以没有任何问题。

问题是,即使我在任务上调用 resume() 并允许它在完成时唤醒我的应用程序,但它似乎也没有这样做。

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

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)

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

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

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 .

我的项目中是否缺少某些设置?我将所有这些代码放入 watchOS 3 中新增的 ExtensionDelegate 中。我还遵守 WKExtensionDelegateURLSessionDownloadDelegate

提前感谢您的帮助!

最佳答案

我成功了!我首先看了很多 WWDC'16 视频/笔记,并将它们与 WatchBackgroundRefresh 进行比较。来自苹果公司的例子。然后,在浏览Apple Dev论坛时,我发现this thread ,与我们遇到的问题相同。在那里,一个叫“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 文件中。

希望这能有所帮助!

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

关于watchkit - 尝试在 watchOS 中进行后台刷新时不会调用 WKURLSessionRefreshBackgroundTask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41156386/

相关文章:

ios - WatchKit:使用 openParentApplication 获取当前位置:回复:

ios - WatchKit 从 iPhone 中关闭的 App 获取数据

ios - 使用storeCachedResponse存储在缓存中后,未检索到URLresponse

swift - 无法在 watchOS 上使用 GameKit (Game Center) 验证本地玩家

ios - SwiftUI 中有 Controller 吗?

ios - 非动画滚动 WKInterfaceTable 到底部

ios - NSURLSession 未到达服务器

ios - 从 Swift 将数据 POST 到 PHP 方法

ios - 我应该为 App Store 提交构建哪个目标,包括 Watch 扩展?

ios - presentMediaPlayerControllerWithURL 不适用于 google tts API