gpt4 book ai didi

background-task - WKWatchConnectivityRefreshBackgroundTask 永远不会在后台触发,但是 WKSnapshotRefreshBackgroundTask

转载 作者:行者123 更新时间:2023-12-04 07:11:16 25 4
gpt4 key购买 nike

我想使用 session.updateApplicationContext(applicationContext). 从 iPhone 在后台更新我的 watch 应用程序状态

在 watch 上的应用程序处于事件状态时发送应用程序联系人确实可以正常工作。
当我激活 watch 上的主页按钮时, watch 应用程序进入后台,handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>)被调用,并且一个 WKSnapshotRefreshBackgroundTask提供。

所以我不明白为什么 WKSnapshotRefreshBackgroundTask被正确触发,但不是 WKWatchConnectivityRefreshBackgroundTask .

Apple’s docs说“当你从配对的 iPhone 接收到后台数据时,系统会在后台启动你的应用程序,实例化一个 WKWatchConnectivityRefreshBackgroundTask对象,并将任务对象传递给扩展委托(delegate)的 handleBackgroundTasks: method.“。

但这不会发生,无论是在设备上还是在模拟器上。有什么问题?

编辑:

为了检查可能出现的问题,我下载了 Apple 的演示项目“QuickSwitch”,可以下载 here .这是应该处理后台任务的代码:

func handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) {
for backgroundTask in backgroundTasks {
if let wcBackgroundTask = backgroundTask as? WKWatchConnectivityRefreshBackgroundTask {
// store a reference to the task objects as we might have to wait to complete them
self.wcBackgroundTasks.append(wcBackgroundTask)
} else {
// immediately complete all other task types as we have not added support for them
backgroundTask.setTaskCompleted()
}
}
completeAllTasksIfReady()
}

在那里,同样的事情发生了 :
我确实在 if 语句的行中设置了一个断点并执行了应用程序。
当 watch 模拟器上的主页按钮被按下时,断点到达 WKSnapshotRefreshBackgroundTask .这没关系(见上文)。
但是,如果在 iPhone 模拟器上选择了不同的行, watchOS 没有安排 WKWatchConnectivityRefreshBackgroundTask ,正如预期的那样。毕竟,这个演示项目应该正是演示了这一点。
也许有人可以尝试演示项目并确认这个问题。

怎么了?

最佳答案

更新我的答案

先说结论

目前WKWatchConnectivityRefreshBackgroundTask只有当 watchOS 扩展的 WCSession 时,才会在 watchOS 模拟器上确定调用。在 notActivated状态并且扩展程序未在前台运行(在后台或已终止)。

在真实设备中,它不会在我的测试中被调用。但苹果文档说它可能。因此,在 Apple 更改其文档之前,您不应该依赖它不会被调用。

WCSession 核心

WCSession Core

对于 WCSession , 当它是 activated ,可以传递userInfo,当对方处于事件状态时,可以获取userInfo。对方不需要在前台激活,它可以在高优先级的后台。

测试结果

这是我的测试结果。

In Simulators and in devices

制作方法WCSession notActivated ?

  • 使用 Xcode 终止您的 watchOS 扩展。 Xcode 将向您的 WKExtension 发送终止信号。
  • 或者不要运行WCSession.activate()在 watchOS 扩展端的代码中。如WCSessionnotActivated默认情况下。


  • -------------以下是旧帖,不想看的可以放心忽略。--------

    理论

    enter image description here

    请先看图,我再解释。

    由于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 .当您的应用程序处于后台时,它会在数据到来时被唤醒,但您无法获取数据,因为您没有 session 。

    如果您同时实现了它们,在大多数情况下,数据将根据您的 watchOS 应用程序的状态进行处理,并且永远不会排队。

    如何证明?

    创建一个新的 watchOS 项目。在iOS部分,添加一个按钮,每次点击按钮,发送一个userInfo到watchOS
    session.transferUserInfo(["send test":""])

    在您的 watchOS 应用中,在 interface.storyboard 中添加标签, 并将其拖至 viewController@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->schemeWatchKit app所以我们可以在 Xcode 中终止 watchOS 应用程序。
  • 运行项目。
  • 当 watchOS 应用显示时,手动打开 iOS 应用。
  • 单击iOS应用程序中的按钮。你可以看到label在 watchOS 中更改了 4。
  • 在 Xcode 中,单击 product->stop (或 cmd+。)。 watchOS 应用程序将消失。
  • 在 iOS 应用程序的按钮上单击一次或多次。然后手动打开 watchOS 应用。这次您将看到 label变化乘以 1 乘以您的点击次数。
  • 当 watchOS 应用程序处于前台时,该步骤将再次为 4。
  • 关于background-task - WKWatchConnectivityRefreshBackgroundTask 永远不会在后台触发,但是 WKSnapshotRefreshBackgroundTask,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40537027/

    25 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com