后台中的URLSessionDownloadTask从不为WKURLSession刷新后台任务触发句柄(_ backgroundTasks:Set <wkrefreshbackgroundtask>)

时间:2017-03-26 23:36:11

标签: ios watchkit apple-watch nsurlsessiondownloadtask watch-os-3

在WatchKit 3.0中安排后台URLSessionDownloadTask时,试着理解原因。函数handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)永远不会为WKURLSession​Refresh​Background​Task触发,但其他任务来自WKApplicationRefreshBackgroundTaskWKSnapshotRefreshBackgroundTask

我在守望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>)触发?

1 个答案:

答案 0 :(得分:0)

您已将PreferredFireDate设置为10秒。正如苹果所说,没有保证这么快就开火。

  

preferredFireDate

     

下一次后台快照刷新任务的时间。系统   尽一切努力在后台唤醒您的应用   在预定时间之后,但不能保证准确的时间。

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

还必须为WKExtension设置委托。

WKExtension.shared().delegate = self //self is an object where handle metod is implemented

编辑

  

后台应用程序刷新任务已预算。通常,系统每小时为扩展坞中的每个应用程序(包括最近使用的应用程序)执行大约一项任务。该预算由扩展坞上的所有应用共享。该系统每小时为每个应用程序执行多个任务,并在活动表盘上进行复杂处理。此预算由表盘上的所有复杂功能分配。预算用完后,系统会延迟您的请求,直到有更多时间可用为止。