在WatchKit 3.0中安排后台URLSessionDownloadTask时,试着理解原因。函数handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)
永远不会为WKURLSessionRefreshBackgroundTask
触发,但其他任务来自WKApplicationRefreshBackgroundTask
和WKSnapshotRefreshBackgroundTask
。
我在守望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>)
触发?
答案 0 :(得分:0)
您已将PreferredFireDate设置为10秒。正如苹果所说,没有保证这么快就开火。
preferredFireDate
下一次后台快照刷新任务的时间。系统 尽一切努力在后台唤醒您的应用 在预定时间之后,但不能保证准确的时间。
当我将此参数设置为30秒时,我不得不等待大约10分钟,直到系统调用了handle方法。
还必须为WKExtension设置委托。
WKExtension.shared().delegate = self //self is an object where handle metod is implemented
编辑
后台应用程序刷新任务已预算。通常,系统每小时为扩展坞中的每个应用程序(包括最近使用的应用程序)执行大约一项任务。该预算由扩展坞上的所有应用共享。该系统每小时为每个应用程序执行多个任务,并在活动表盘上进行复杂处理。此预算由表盘上的所有复杂功能分配。预算用完后,系统会延迟您的请求,直到有更多时间可用为止。