ios - 后台的 URLSessionDownloadTask 从不触发 handle(_ backgroundTasks : Set<WKRefreshBackgroundTask>) for WKURLSession​Refresh​Background​Task

标签 ios watchkit apple-watch nsurlsessiondownloadtask watchos-3

试图理解为什么在 WatchKit 3.0 中安排后台 URLSessionDownloadTask 时。函数 handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)从不触发 WKURLSession​Refresh​Background​Task , 但其他任务像 WKApplicationRefreshBackgroundTask 一样完成和 WKSnapshotRefreshBackgroundTask .

我在 watch 中的代码 ExtensionDelegate ...

func applicationDidBecomeActive() {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.

    scheduleBackgroundRefresh(in: 10)
}

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
    // Sent when the system needs to launch the application in the background to process tasks. Tasks arrive in a set, so loop through and process each one.
    for task in backgroundTasks {
        // Use a switch statement to check the task type
        switch task {
        case let backgroundTask as WKApplicationRefreshBackgroundTask:
            // Be sure to complete the background task once you’re done.
            scheduleURLSession()
            backgroundTask.setTaskCompleted()
        case let snapshotTask as WKSnapshotRefreshBackgroundTask:
            // Snapshot tasks have a unique completion call, make sure to set your expiration date
            snapshotTask.setTaskCompleted(restoredDefaultState: true, estimatedSnapshotExpiration: Date.distantFuture, userInfo: nil)
        case let connectivityTask as WKWatchConnectivityRefreshBackgroundTask:
            // Be sure to complete the connectivity task once you’re done.
            connectivityTask.setTaskCompleted()
        case let urlSessionTask as WKURLSessionRefreshBackgroundTask: // This is never fired, Don't know why, arrrgggggg
            // Be sure to complete the URL session task once you’re done.

            let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: urlSessionTask.sessionIdentifier)
            let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: self, delegateQueue: nil) // delegate set to self here after rejoining the session

            print("Rejoining session ", backgroundSession)

            urlSessionTask.setTaskCompleted() // probably need to postpone this until the url `urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)` has completed, but either way, this switch case is never met
        default:
            // make sure to complete unhandled task types
            task.setTaskCompleted()
        }
    }
}

func scheduleURLSession() {
    if let url = URL(string: "https://some.path.com") {
        let backgroundConfigObject = URLSessionConfiguration.background(withIdentifier: NSUUID().uuidString)
        let backgroundSession = URLSession(configuration: backgroundConfigObject, delegate: nil, delegateQueue: nil) // nil delegate here because delegate is "supposed" to be set in `handle(_ backgroundTasks:)` delegate method ("Rejoining session"). 

        let task = backgroundSession.downloadTask(with: url)
        task.resume()
    } else {
        print("Url error")
    }
}

func scheduleBackgroundRefresh(in seconds: TimeInterval) {
    let fireDate = Date(timeIntervalSinceNow: seconds)
    // optional, any SecureCoding compliant data can be passed here
    let userInfo = ["reason" : "background update"] as NSDictionary

    WKExtension.shared().scheduleBackgroundRefresh(withPreferredDate: fireDate, userInfo: userInfo) { (error) in
        if (error == nil) {
            print("successfully scheduled background task, use the crown to send the app to the background and wait for handle:BackgroundTasks to fire.")
        }
    }
}

Here's Apple's sample code for reference

知道为什么 URLSessionDownloadTask在后台永远不会触发 handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)开火?

最佳答案

您已将 preferredFireDate 设置为 10 秒。正如苹果所说,不能保证这么快就触发处理方法。

preferredFireDate

The time of the next background snapshot refresh task. The system makes every effort to wake your app in the background at some point after the scheduled time, but the precise time is not guaranteed.

当我将此参数设置为 30 秒时,我不得不等待大约 10 分钟,直到系统调用 handle 方法。

您还必须为 WKExtension 设置委托(delegate)。

WKExtension.shared().delegate = self//self是一个实现handle方法的对象

编辑

Background app refresh tasks are budgeted. In general, the system performs approximately one task per hour for each app in the dock (including the most recently used app). This budget is shared among all apps on the dock. The system performs multiple tasks an hour for each app with a complication on the active watch face. This budget is shared among all complications on the watch face. After you exhaust the budget, the system delays your requests until more time becomes available.

关于ios - 后台的 URLSessionDownloadTask 从不触发 handle(_ backgroundTasks : Set<WKRefreshBackgroundTask>) for WKURLSession​Refresh​Background​Task,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/43035869/

相关文章:

ios - 如何从当前图形上下文创建 UIImage?

ios - 在运行时使用客户端 ID 控制的 Paypal

ios - iPhone 应用程序启动时无法从 Watch 读取 NSUserDefaults

ios - 可以从 iOS 应用程序打开 watchOS 应用程序吗?

ios - 分发配置文件是否来自分发证书?

ios - NSURLCache,连同 NSURLSession,不尊重 : Cache-Control: max-age:86000, private,must-revalidate

ios - watchOS 通知安静地传递

ios - WatchKit XCODE 6.3 问题

objective-c - WatchKit 中状态栏的高度

ios - 当用户在 Table View 行上切换到 Watchkit 中的另一个详细界面 Controller 时需要将数据传递