更新我的答案
先说结论
当前WKWatchConnectivityRefreshBackgroundTask
仅在 watchOS 扩展WCSession
程序处于notActivated
状态且扩展程序未在前台运行(在后台或终止)时在 watchOS 模拟器上确定调用。
在真实设备中,它不会在我的测试中被调用。但苹果文档说它可能。因此,在 Apple 更改其文档之前,您不应该依赖它不会被调用。
WCSession 核心
对于WCSession
,当为 时activated
,可以传输用户信息,当对方处于活动状态时,可以获取用户信息。对方不需要在前台激活,它可以在高优先级的后台。
测试结果
这是我的测试结果。
如何制作WCSession
notActivated
?
- 使用 Xcode 终止您的 watchOS 扩展。Xcode 将向您的 WKExtension 发送终止信号。
- 或者不要
WCSession.activate()
在 watchOS Extension 端的代码中运行。默认情况WCSession
下。notActivated
-------------以下是旧帖,不想看的可以放心忽略。--------
理论
请先看图,我再解释。
由于watchOS的历史,既有WCSessionDelegate
接收功能(从watchOS 2.0开始),也有WKExtensionDelegate.handle(_:)
功能(从watchOS 3.0开始)。
尽管它们都声称是后台处理,但前者仅在您的应用程序处于前台时才立即起作用。如果您的应用程序不在前台(在后台或被终止),数据将排队,并在您的应用程序再次进入前台时立即执行。
WKExtensionDelegate.handle(_:)
真的在后台工作。但是,WKExtensionDelegate.handle(_:)
如果您使用 Xcode,建议使用它并做好充分准备,但它是可选的。
如果您不WKExtensionDelegate.handle(_:)
通过评论来实施。您的应用程序以 watchOS 2.0 方式运行。
如果您实施WKExtensionDelegate.handle(_:)
但您WCSession
的 watchOS 应用程序中没有。结果很棘手。当您 watchOS 应用程序处于前台时,您将不会获得任何数据,因为您没有WCSession
. 当您的应用程序处于后台时,它会在数据到来时被唤醒,但您无法获取数据,因为您没有会话。
如果您同时实现了它们,在大多数情况下,数据将根据您的 watchOS 应用程序的状态进行处理,并且永远不会排队。
如何证明?
创建一个新的 watchOS 项目。在iOS部分,添加一个按钮,每次点击按钮,发送一个userInfo到watchOS
session.transferUserInfo(["send test":""])
在你的 watchOS 应用中,在 中添加一个标签interface.storyboard
,并将其拖到viewController
as 中@IBOutlet var label: WKInterfaceLabel!
,并同时实现WKExtensionDelegate.handle(_:)
和func session(WCSession, didReceiveUserInfo: [String : Any] = [:])
appDelegate
。
var total = 0
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.
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.
total += 1
DispatchQueue.main.async {
if let viewController = WKExtension.shared().rootInterfaceController as? InterfaceController {
viewController.label.setText(String(self.total))
}
}
connectivityTask.setTaskCompleted()
case let urlSessionTask as WKURLSessionRefreshBackgroundTask:
// Be sure to complete the URL session task once you’re done.
urlSessionTask.setTaskCompleted()
default:
// make sure to complete unhandled task types
task.setTaskCompleted()
}
}
}
public func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) {
total += 4
DispatchQueue.main.async {
if let viewController = WKExtension.shared().rootInterfaceController as? InterfaceController {
viewController.label.setText(String(self.total))
}
}
}
如果WKExtensionDelegate.handle(_:)
运行,我们加total
1。如果func session(WCSession, didReceiveUserInfo: [String : Any] = [:])
运行,我们加total
4。
调试
在 Xcode 中,选择product->scheme
asWatchKit app
这样我们就可以在 Xcode 中终止 watchOS 应用程序。
- 运行项目。
- 当 watchOS 应用显示时,手动打开 iOS 应用。
- 单击iOS应用程序中的按钮。您可以看到
label
watchOS 中的 4 变化。
- 在 Xcode 中,单击
product->stop
(或 cmd+.)。watchOS 应用程序将消失。
- 在 iOS 应用程序的按钮上单击一次或多次。然后手动打开 watchOS 应用。这次您将看到
label
更改乘以 1 乘以您的点击次数。
- 当 watchOS 应用程序处于前台时,该步骤将再次为 4。