WKWatchConnectivityRefreshBackgroundTask永远不会在后台触发,但是WKSnapshotRefreshBackgroundTask [英] WKWatchConnectivityRefreshBackgroundTask is never triggered in background, but WKSnapshotRefreshBackgroundTask

查看:164
本文介绍了WKWatchConnectivityRefreshBackgroundTask永远不会在后台触发,但是WKSnapshotRefreshBackgroundTask的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想使用session.updateApplicationContext(applicationContext).

在手表上的应用程序处于活动状态时发送应用程序联系人确实可以正常工作.
当我激活手表上的主页按钮时,手表应用会转到后台,调用handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>),并提供一个WKSnapshotRefreshBackgroundTask.

Sending an application contact while the app on the watch is active does work properly.
When I activate the home button on the watch, the watch app goes to the background, handle(_ backgroundTasks: Set<WKRefreshBackgroundTask>) is called, and a WKSnapshotRefreshBackgroundTask is provided.

所以我不明白为什么正确触发了WKSnapshotRefreshBackgroundTask而不是触发WKWatchConnectivityRefreshBackgroundTask的原因.

So I don’t understand why a WKSnapshotRefreshBackgroundTask is triggered properly, but not a WKWatchConnectivityRefreshBackgroundTask.

",当您从配对的iPhone接收背景数据时,系统会在后台启动您的应用,实例化WKWatchConnectivityRefreshBackgroundTask对象,然后将任务对象传递给扩展委托的handleBackgroundTasks :方法..

Apple’s docs say „When you receive background data from the paired iPhone, the system launches your app in the background, instantiates a WKWatchConnectivityRefreshBackgroundTask object, and passes the task object to your extension delegate’s handleBackgroundTasks: method.".

但是,无论是在设备上还是在模拟器上,都不会发生这种情况.有什么问题吗?

But this does not happen, neither on a device, nor on the simulator. What could be wrong?

要检查可能出了什么问题,我下载了苹果的演示项目"QuickSwitch",该项目可以下载

To check what might be wrong, I downloaded Apple’s demo project „QuickSwitch" that can be downloaded here. Here is the code that should handle background tasks:

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语句的行中设置了一个breakponint并执行了该应用程序.
当按下手表模拟器上的主页按钮时,可以通过WKSnapshotRefreshBackgroundTask到达断点.可以(请参见上文).
但是,如果在iPhone模拟器上选择了不同的行,则 watchOS不会如预期的那样安排WKWatchConnectivityRefreshBackgroundTask .毕竟,这个演示项目应该完全演示这一点.
也许有人可以尝试演示项目并确认是否存在此问题.

There, the same happens:
I did set a breakponint in the line of the if statement and executed the app.
When the home button on the watch simulator is pressed, the breakpoint is reached with a WKSnapshotRefreshBackgroundTask. This is OK (see above).
However, if a different line is selected on the iPhone simulator, watchOS does not schedule a WKWatchConnectivityRefreshBackgroundTask, as expected. After all, this demo project should demo exactly this point.
Maybe somebody could try the demo project and confirm this problem or not.

怎么了?

推荐答案

更新我的答案


结论优先

当前,只有在watchOS扩展程序的WCSession处于notActivated状态并且该扩展程序不在前台(在后台或终止)中运行时,才能在watchOS Simulator上确定地调用WKWatchConnectivityRefreshBackgroundTask.

Update my answer


Conclusion first

Currently WKWatchConnectivityRefreshBackgroundTask is only called for sure on a watchOS Simulator when the watchOS extension's WCSession is in notActivated state and the extension is not running in foreground (in background or terminated).

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

In real devices, it won't be called in my tests. But Apple docs says it may. So you shouldn't rely on it won't be called until Apple changes its docs.

对于WCSession,当它是activated时,您可以传输userInfo,而当对方处于活动状态时,它可以获取userInfo.对方不需要在前台被激活,它可以在高优先级的后台.

For WCSession, when it is activated, you can transfer userInfo, and when the counterpart is active, it can get the userInfo. The counterpart won't need to be in foreground to be activated, it can be in a high priority background.

这是我的测试结果.

  1. 使用Xcode终止watchOS扩展. Xcode会向您的WKExtension发送终止信号.
  2. 或者不要在watchOS扩展端的代码中运行WCSession.activate().由于WCSession默认为notActivated.
  1. Using Xcode terminate your watchOS Extension. Xcode will send a kill signal to your WKExtension.
  2. Or don't run WCSession.activate() in your code on watchOS Extension side. As WCSession is notActivated by default.


-------------下面是旧帖子,如果您不想阅读,可以安全地忽略.---------------- ---


-------------below are old post, you can ignore safely if you don't want to read.-------------------

请先看图片,然后我会解释.

Please watch the picture first then I will explain.

由于watchOS的历史,既有WCSessionDelegate接收功能(从watchOS 2.0开始)又有WKExtensionDelegate.handle(_:)功能(从watchOS 3.0开始).

Because of the history of watchOS, there are both WCSessionDelegate receiving functions (start from watchOS 2.0) and WKExtensionDelegate.handle(_:) function (start from watchOS 3.0).

尽管它们都声称是后台交易,但前者仅在您的应用程序处于前台时才可以立即使用.如果您的应用程序不在前台(在后台或正在终止),则数据将排队,并在稍后再次成为前台时立即执行.

Although they all claims to be background dealing, the former only works immediately when your app is in foreground. The data will be queued if your app is not in foreground (in background or being terminated) and executed immediately later when your app becomes in foreground again.

WKExtensionDelegate.handle(_:)确实在后台运行.但是,WKExtensionDelegate.handle(_:)是可选的,尽管建议使用它,并且如果您使用Xcode,请做好充分的准备.

WKExtensionDelegate.handle(_:) is really working in background. However, the WKExtensionDelegate.handle(_:) is optional although it is recommended and well-prepared if you use Xcode.

如果未通过注释实现WKExtensionDelegate.handle(_:).您的应用程序以watchOS 2.0方式工作.

If you don't implement WKExtensionDelegate.handle(_:) by commenting it. You app works in a watchOS 2.0 way.

如果实现了WKExtensionDelegate.handle(_:),但watchOS应用程序中没有WCSession.结果是棘手的.当您的watchOS应用程序处于前台状态时,您将不会获得任何数据,因为您没有WCSession.当您的应用程序处于后台运行时,数据到来时将被唤醒,但由于没有会话,因此您无法获取数据.

If you implement WKExtensionDelegate.handle(_:) but you don't have a WCSession in your watchOS app. The result is tricky. You won't get any data when you watchOS app is in foreground, as you don't has a WCSession. When your app is in background, it will be waken when data comes, but you can't get the data as you don't have a session.

如果在大多数情况下都实现了这两种方法,则会根据watchOS应用的状态来处理数据,并且永远不会排队.

If you implemented them both, which are in most situations, data comes will be dealt depending on the state of your watchOS app and never be queued.

创建一个新的watchOS项目.在iOS部分中,添加一个按钮,每次单击该按钮时,将userInfo发送给watchOS

Create a new watchOS project. In iOS part, add a button, each time you clicked the button, send a userInfo to watchOS

session.transferUserInfo(["send test":""])

在watchOS应用中,在interface.storyboard中添加标签,并将其作为@IBOutlet var label: WKInterfaceLabel!拖到viewController,并同时实现WKExtensionDelegate.handle(_:)func session(WCSession, didReceiveUserInfo: [String : Any] = [:]) appDelegate.

In your watchOS app, add a label in interface.storyboard, and drag it to viewController as @IBOutlet var label: WKInterfaceLabel!, and implement both WKExtensionDelegate.handle(_:) and 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.

If WKExtensionDelegate.handle(_:) runs, we add total by 1. If func session(WCSession, didReceiveUserInfo: [String : Any] = [:]) runs, we add total by 4.

在Xcode中,选择product->scheme作为WatchKit app,以便我们可以在Xcode中终止watchOS应用.

In Xcode, choose product->scheme as WatchKit app so we can terminate the watchOS app in Xcode.

  1. 运行项目.
  2. 当watchOS应用显示时,请手动打开iOS应用.
  3. 单击iOS应用中的按钮.您可以看到watchOS中的label更改为4.
  4. 在Xcode中,单击product->stop(或cmd +.). watchOS应用程序将消失.
  5. 在iOS应用程序的按钮上单击一次或多次.然后手动打开watchOS应用程序.这次您会看到label的变化是1乘以您的点击次数.
  6. 当watchOS应用程序处于前台时,步骤将再次为4.
  1. run the project.
  2. when watchOS app shows, open iOS app manually.
  3. clicked the button in iOS app. You can see the label in watchOS changes by 4.
  4. in Xcode, click product->stop(or cmd+.). watchOS app will disappear.
  5. click one or more times on iOS app's button. Then manually open the watchOS app. You will see this time the label changes by 1 multiply your clicks.
  6. The step will be 4 again when watchOS app is in foreground.

这篇关于WKWatchConnectivityRefreshBackgroundTask永远不会在后台触发,但是WKSnapshotRefreshBackgroundTask的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆