天道酬勤,学无止境

how to wake up iOS parent app with sendMessage from complicationController

I am trying to wake up the iOS parent app by sending a message from watchkit extension.

This though does only work when below sendMessage function is called from the watchApp / ViewController. When it is called from ComplicationController, the message is sent, but the iOS parent app does now wake up.

Any advice appreciated. (please any code reference in Swift)

Here the simplified code:

In AppDelegate and ExtensionDelegate:

override init() {
    super.init()
    setupWatchConnectivity()
}

private func setupWatchConnectivity() {
    if WCSession.isSupported() {
        let session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}

In ExtensionDelegate: (no problem here, message is successfully sent)

func sendMessage(){
        let session = WCSession.defaultSession()
        let applicationData:[String:AnyObject] = ["text":"test", "badgeValue": 100 ]

        session.sendMessage(applicationData, replyHandler: {replyMessage in
            print("reply received from iphone")
            }, errorHandler: {(error ) -> Void in
                // catch any errors here
                print("no reply message from phone")
        })
    }
    print("watch sent message")

}

In AppDelegate: (not received when iOS app not running / not in foreground)

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
    let text = message["text"] as! String
    let badgeValue = message["badgeValue"] as! Int

    dispatch_async(dispatch_get_main_queue()) { () -> Void in

        print("iphone received message from watch App")
        self.sendNotification(text, badgeValue: badgeValue)
        let applicationDict = ["wake": "nowAwake"]
        replyHandler(applicationDict as [String : String])

    }

}

this is how the function is called from Complication Controller (which does send the message but not awake the parent app):

  func requestedUpdateDidBegin(){

        dispatch_async(dispatch_get_main_queue()) { () -> Void in

            let extensionDelegate = ExtensionDelegate()
            extensionDelegate.loadData()

        }
    }

评论

The main problem is that you're trying to include (nested) asynchronous calls within your complication data source. However, your requested update will have reached the end of its method, and no timeline update will actually take place (since you didn't reload or extend the timeline, and even if you had, no new data would have been received in time for the current update).

Since no new data would be available for the scheduled update, you'd have to perform a second update to use the new data once it was received. Performing two back-to-back updates is not only unnecessary, it wastes more of your daily complication budget.

Apple recommends that you fetch and cache the data in advance of the update, so the complication data source can directly return the requested data to the complication server.

The job of your data source class is to provide ClockKit with any requested data as quickly as possible. The implementations of your data source methods should be minimal. Do not use your data source methods to fetch data from the network, compute values, or do anything that might delay the delivery of that data. If you need to fetch or compute the data for your complication, do it in your iOS app or in other parts of your WatchKit extension, and cache the data in a place where your complication data source can access it. The only thing your data source methods should do is take the cached data and put it into the format that ClockKit requires.

How can you update the complication?

  • Use background updates from the phone to transfer the data to be on hand for the complication's next scheduled update. transferUserInfo and updateApplicationContext are suited for this type of update.

  • Use transferCurrentComplicationUserInfo to immediately transfer complication data and update your timeline.

Both of these approaches have the advantage of only needing one update to occur.

受限制的 HTML

  • 允许的HTML标签:<a href hreflang> <em> <strong> <cite> <blockquote cite> <code> <ul type> <ol start type> <li> <dl> <dt> <dd> <h2 id> <h3 id> <h4 id> <h5 id> <h6 id>
  • 自动断行和分段。
  • 网页和电子邮件地址自动转换为链接。

相关推荐
  • 结合 WatchConnectivity 和复杂功能(Combining WatchConnectivity and Complications)
    问题 我希望我的复杂功能通过 Watch Connectivity 从 iPhone 获取数据。 我正在使用sendMessage即时消息技术。 当我尝试获取数据时,我不希望我的 iPhone 应用程序打开,因此这需要在后台运行。 在我的 iPhone 上的 ViewController 中: import UIKit import WatchConnectivity class ViewController: UIViewController, WCSessionDelegate { var session: WCSession! override func viewDidLoad() { super.viewDidLoad() if WCSession.isSupported() { self.session = WCSession.defaultSession() self.session.delegate = self self.session.activateSession() } } func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { if message
  • WatchKit2 错误代码 7007“无法访问配对设备上的会话”的真正原因是什么?(What is the very reason for WatchKit2 error code 7007 “session on paired device is not reachable”)
    问题 我正在为我的 Apple WatchOS2 应用程序开发概览视图。 我目前还没有完全理解稳定 WatchConnectivity 连接的先决条件。 我有一个奇怪的情况,在模拟器中我的 ComplicationController 可以成功发送一个 sendMessage 请求。 当我尝试看一眼时,sendMessage 请求失败: Error Domain=WCErrorDomain Code=7007 "WatchConnectivity session on paired device is not reachable." UserInfo={NSLocalizedDescription=WatchConnectivity session on paired device is not reachable. 我不得不承认,我没有在模拟器上启动我的应用程序。 但是为什么 ComplicationController 可以通信而 WatchController 不能。 我在互联网上没有找到关于错误 7007 的解释。 override func awakeWithContext(context: AnyObject?) { super.awakeWithContext(context) WCSession.defaultSession().sendMessage([
  • What is the very reason for WatchKit2 error code 7007 “session on paired device is not reachable”
    I am developing a glance view for my Apple WatchOS2 app. I'am currently didn't fully understand the prequisites for a stable WatchConnectivity connection now. I have the strange situation, that in the simulator my ComplicationController could successfully a sendMessage Request. When I try to look at my glance, the sendMessage request failed with: Error Domain=WCErrorDomain Code=7007 "WatchConnectivity session on paired device is not reachable." UserInfo={NSLocalizedDescription=WatchConnectivity session on paired device is not reachable. I have to admit, that I didn't start my app on the
  • 获取数据复杂化:未调用 ExtensionDelegate(Get Data to Complication: ExtensionDelegate not Called)
    问题 (看起来这个问题在前几周已经被其他人遇到了,但我还没有找到任何解决方案。) 我正在尝试做一件非常基本的事情:从我的 iOS 应用程序或我的 Watch 应用程序获取数据到我的 Complication Controller。 事实证明,我完成这件事的能力比我想象的要差得多。 watchOS 2 Transition Guide 指出我应该使用以下代码“[获取]来自扩展委托的所需数据”: ExtensionDelegate* myDelegate = [[WKExtension sharedExtension] delegate]; NSDictionary* data = [myDelegate.myComplicationData objectForKey:ComplicationCurrentEntry]; 伟大的。 除了,我一直无法弄清楚如何让它在扩展端工作。 尽管更重要的是,我似乎甚至无法从复杂控制器启动中运行扩展委托代码。 当我运行复杂功能时,我收到以下消息:“扩展收到唤醒复杂功能支持的请求。” 但是,任何扩展委托的方法中的代码似乎都没有运行。 我还在每个方法中设置了断点,并且没有一个断点被命中。 它看起来也像“transferCurrentComplicationUserInfo:”也被建议用于复杂功能更新,尽管目前还不清楚它是如何使用的。 据我所知
  • 调用ExtensionDelegate来创建/刷新用于并发症的数据(Call ExtensionDelegate to create/refresh data for Complication)
    问题 我所有的数据创建都在ExtensionDelegate.swift完成。 问题是我的ComplicationController.swift getCurrentTimelineEntryForComplication函数之前没有调用ExtensionDelegate.swift 。 有任何想法吗? 这是我的代码和详细信息: 因此,我的ComplicationController.swift数组extEvnts为空: func getCurrentTimelineEntryForComplication(complication: CLKComplication, withHandler handler: ((CLKComplicationTimelineEntry?) -> Void)) { let extEvnts = ExtensionDelegate.evnts } 因为尚未调用我的ExtensionDelegate.swift ,所以将为数组创建数据: class ExtensionDelegate: NSObject, WKExtensionDelegate, WCSessionDelegate { private let session = WCSession.defaultSession() var receivedData = Array
  • 如何从watchOS 2唤醒iPhone应用程序?(How to wake up iPhone app from watchOS 2?)
    问题 我有一个具有非常丰富的网络层的应用程序,而我的Apple Watch应用程序则取决于所有型号。 不幸的是,该应用程序的模块化程度不足,无法在手表应用程序中使用此图层。 我通过使用openParentApplication解决了此问题:唤醒iPhone应用程序,执行请求并返回结果。 在watchOS 2中,此方法已消失,我应该使用WatchConnectivity。 最好的方法是发送userInfo字典。 但是,如何唤醒iPhone应用程序来处理我的请求? 要获取有关新的userInfo的通知,我必须使用WCSessionDelegate,为此,我需要一个WCSession对象。 但是我应该何时创建呢? 以及如何唤醒应用程序? 回答1 我向苹果工程师询问了有关此问题,并获得了以下提示:iOS应用程序应在后台任务中启动。 因此,以下内容对我来说非常有效: UIApplication *application = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier identifier = UIBackgroundTaskInvalid; dispatch_block_t endBlock = ^ { if (identifier != UIBackgroundTaskInvalid) {
  • WCSession sendMessage in Xcode 7.0 (7A218) Simulator
    I use sendMessage from iWatch (Simulator) to iOS to awake iOS app: NSDictionary *userInfo = [[NSDictionary alloc]initWithObjectsAndKeys:@"userInfo", @"key", nil]; if ([[WCSession defaultSession] isReachable]){ //iPhone is reachable NSLog(@"iPhone is reachable"); [[WCSession defaultSession] sendMessage:userInfo replyHandler:^(NSDictionary<NSString *,id> * _Nonnull replyMessage) { NSLog(@"ReplyHandler run"); } errorHandler:^(NSError * _Nonnull error) { NSLog(@"iWatch sendMessage Error: %@", error); } But I found that sendMessage only works if iOS app counterpart is either in Background or
  • WatchKit Complication:从扩展委托获取并发症数据(WatchKit Complication: get Complication data from extension delegate)
    问题 我的 WatchKit 扩展中有我需要的所有数据(从 iOS 应用程序传递)。 我用WatchKit InterfaceController的数据填了一张表格,效果很好。 我试图找出在我的 WatchKit ComplicationController获取相同数据的最佳方法。 目前,在InterfaceController ,数据使用didReceiveUserInfo传入: func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) { if let beachValue = userInfo["Surf"] as? String { places.append(Place(dataDictionary: ["Surf" : surfValue])) } else { print("Something went wrong") } } 我是否需要在我的ComplicationController调用这个相同的WCSession方法并再次抓取整个数据,或者有没有更简单的方法让我访问在ComplicationController使用的相同数据? 任何帮助表示赞赏。 谢谢! 编辑: 我的表功能: func makeTable() { // Per SO let
  • 如何使用 WatchConnectivity 在 iOS 和 Watch 应用之间共享信息?(How can I share information between my iOS and Watch apps using WatchConnectivity?)
    问题 [免责声明:此问题旨在作为一个 wiki 问题来回答有关在watchkit和watch-os标签下在 iOS 和手表应用程序之间发送数据的常见问题。] 我正在开发 Apple Watch 应用程序,并希望在iOS应用程序与其WatchKit extension程序之间发送数据。 我查看了WatchConnectivity框架,但并不真正了解其所有方法之间的区别。 如果我希望即使我的应用程序在后台也能发送数据,我应该使用哪个函数? 我应该使用哪个函数向 Watch 发送 UI 更新? 我应该使用哪个函数来发送大数据? 回答1 在撰写此答案时( watchOS3是当前的稳定版本, watchOS4处于测试阶段), iOS应用程序与其WatchKit extension之间直接通信的唯一选择是 WatchConnectivity 框架。 (我说的很直接,因为这个问答不涉及使用CloudKit等云技术从一台设备上传文件到互联网并在另一台设备上下载。 ) 首先,我们来讨论WCSession的哪个函数应该用于什么目的。 对于代码示例,请向下滚动。 在深入研究细节之前,简要介绍每个功能以及何时使用它们: updateApplicationContext : 同步应用程序之间的状态,发送要显示在 UI 上的数据(仅用于发送小块数据) transferUserInfo : 在后台发送数据字典
  • “消息回复时间太长了。” - Watch OS 3 的手表连接问题(“Message reply took too long.” - Watch Connectivity Issues with Watch OS 3)
    问题 在我的项目中,我使用Watch Connectivity与 Watch 和 iPhone 之间发送消息。 我可以在启动应用程序时向手机发送消息并接收字符串数组,但是在使用操作时出现以下错误; 错误域=WCErrorDomain 代码=7012 “消息回复时间太长。” 这是设置的方式; 首先,手表向手机发送一条消息,然后手机发送一组字符串以显示在WKInterfaceTable 。 这有时在加载应用程序时有效。 (我获取所有名为Items NSManagedObjects 并使用它们的title字符串属性存储在名为watchItems的array 。 但是,我在手表上有一个操作来删除数组中的所有项目并用新数据刷新表。 手表上的动作使用sendMessage函数将item发送到手机从数组中删除,然后手机将新更新的数组发送给手表,手表更新表。 但是,我要么返回相同的数组,要么返回错误。 非常简单,所以在 Swift 3 和 Watch OS3/iOS 10 之前,一切实际上都运行良好; 整个应用程序曾经可以工作。 这是我如何设置一切; 电话应用程序委托 import WatchConnectivity class AppDelegate: UIResponder, UIApplicationDelegate, WCSessionDelegate { var session
  • WatchOS2 WCSession sendMessage doesn't wake iPhone on background
    This is being tested on both Simulator and real physical device iphone5s. I tried to use WCSession sendMessage to communicate from WatchOS2 extension to iPhone iOS9 code. It works well when iphone app is running either in the foreground and background mode. But If I kill the iPhone app (not running app at all), then I always got errorHandler timeout. So Watch cannot communicate with iPhone anymore. "Error Domain=WCErrorDomain Code=7012 "Message reply took too long." UserInfo={NSLocalizedDescription=Message reply took too long., NSLocalizedFailureReason=Reply timeout occured.}". I think it
  • 打开父应用程序 (WatchOS 2.x+)(Open Parent Application (WatchOS 2.x+))
    问题 我正在尝试从父应用程序获取更新,但我不想在从 Apple Watch 发送请求时将父应用程序置于前台。 我最终希望将父应用程序置于后台状态,让它运行所需的方法并将其发送回手表。 具体来说,有没有办法打开父应用程序并让它临时驻留在 WatchOS 2.0+ 的后台状态? 我研究过这个: [WKInterfaceController openParentApplication:[NSDictionary new] 回复:nil]; 但这显然无法启动 Watch OS 2.0。 (父应用程序)应用程序委托: @interface InterfaceController() <WCSessionDelegate> @property (unsafe_unretained, nonatomic) IBOutlet WKInterfaceLabel *networkConnectionLabel; @end @implementation InterfaceController - (void)awakeWithContext:(id)context { [super awakeWithContext: context]; } - (void) willActivate { [super willActivate]; [self startSessionToParentDevice];
  • 为什么从 WatchKit 扩展程序向 iOS 发送消息并得到回复如此缓慢?(Why sending message from WatchKit extension to iOS and getting back a reply is so slow?)
    问题 我正在使用sendMessage方法从 WatchKit 扩展程序向 iOS 应用程序发送消息。 平均需要大约230 毫秒才能收到回复。 时间不取决于 iOS 应用程序是在屏幕上还是在后台运行。 230 毫秒大约是光在地球圆周上往返所需的时间。 但是当我测试时,手机距离我的手表 30 厘米。 问题: 为什么这么慢? 它应该这么慢吗? 有没有办法让它更快? 观察:根据我之前在 watchOS 1 中的实验,通信速度要快一些,过去大约需要 50 毫秒的往返时间。 从 WatchKit 扩展发送消息 let session = WCSession.defaultSession() session.sendMessage(["message from watch":"🌷"], replyHandler: { reply in // Getting reply from iOS app here }, errorHandler: nil) 从 iOS 应用程序接收消息 func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { replyHandler(["reply from iOS"
  • 从挂起模式唤醒后如何打开显示器? [关闭](How to turn on monitor after wake-up from suspend mode? [closed])
    问题 关闭。 这个问题需要更加集中。 它目前不接受答案。 想改善这个问题吗? 更新问题,使其仅通过编辑这篇文章来关注一个问题。 4年前关闭。 改进这个问题 我需要将 PC 从睡眠状态唤醒以使用 C# 执行一些操作。 我使用了CreateWaitableTimer函数,一切正常。 在特定时间,PC 会唤醒,但显示器仍处于省电模式(已关闭)! 所以我想知道,唤醒后如何打开显示器? PS 我已经尝试过“关于如何打开/关闭/待机显示器的完整指南” - 使用 SendMessage (Codeproject) 和 SetThreadExecutionState(ES_DISPLAY_REQUIRED) - 它对我不起作用。 有任何想法吗? 回答1 对我来说,使用 pinvoke 调用SendMessage效果很好。 csharp 的代码示例: using System; using System.Runtime.InteropServices; namespace MyDummyNamespace { class MyProgram { private static int Main(string[] args) { // your program code here // ... NativeMethods.MonitorOff(); System.Threading.Thread
  • 使用watchOS2中的WatchConnectivity在iOS和WatchOS之间发送消息(Send messages between iOS and WatchOS with WatchConnectivity in watchOS2)
    问题 我观看了WWDC2015,发现您现在可以在手表上开发本机应用程序。 这打开了很多功能,我想知道如何在iOS应用程序和AppleWatch应用程序之间发送数据。 我看到有一个名为WatchConnectivity的新框架。 来回发送数据时,我将如何使用它?我有哪些选择? 回答1 手表连通性 首先,应该相互通信的两个类(iOS和watchOS)需要符合<WCSessionDelegate>和#import WatchConnectivity框架 在发送数据之前,您需要检查您的设备是否能够发送数据 if ([WCSession isSupported]) { WCSession *session = [WCSession defaultSession]; session.delegate = self; [session activateSession]; NSLog(@"WCSession is supported"); } 然后,如果您希望使用“交互式消息传递”(sendMessage API),则需要先查看其他设备是否可访问: if ([[WCSession defaultSession] isReachable]) { //Here is where you will send you data } “后台操作” API不需要在您调用WCSession
  • Combining WatchConnectivity and Complications
    I want my complication to get data from the iPhone via Watch Connectivity. I am using sendMessage Instant Messaging technology. I don't want my iPhone app to be open when I try to get data, so this needs to work in the background. In my ViewController on my iPhone: import UIKit import WatchConnectivity class ViewController: UIViewController, WCSessionDelegate { var session: WCSession! override func viewDidLoad() { super.viewDidLoad() if WCSession.isSupported() { self.session = WCSession.defaultSession() self.session.delegate = self self.session.activateSession() } } func session(session
  • WatchKit Complication: get Complication data from extension delegate
    I have all the data I need in my WatchKit Extension (passed from the iOS app). I used the data in the WatchKit InterfaceController to fill in a table, which works perfectly. I'm trying to figure out the best way to get that same data in my WatchKit ComplicationController. Currently, in the InterfaceController, the data gets passed in using didReceiveUserInfo: func session(session: WCSession, didReceiveUserInfo userInfo: [String : AnyObject]) { if let beachValue = userInfo["Surf"] as? String { places.append(Place(dataDictionary: ["Surf" : surfValue])) } else { print("Something went wrong") } }
  • WatchOS 2 - iOS UserDefaults 共享(WatchOS 2 - iOS UserDefaults sharing)
    问题 我正在尝试在 iOS 和 WatchOS 2 之间同步用户详细信息。在以前版本的 WatchKit 应用程序组中共享此类首选项非常好,但在版本 2 中我正在为同样的事情而苦苦挣扎。 现在我尝试使用WCSession的transferUserInfo:方法发送 userInfo,然后将该 userInfo 保存到 watchOS 的 userDefaults 中。 但问题是对于这样的细节手表必须首先要求 iPhone 发送 UserInfo。 如果没有使用 iPhone 应用程序,那么在这种情况下 Watch App 不会反映 userInfo 的变化。 有没有人对 WatchOS 2 中的这种实现有想法? 我做得对吗,请建议是否有人对此有所了解。 回答1 如果您在手表上使用WCSession的sendMessage API,它将在后台唤醒 iOS 应用(如果它尚未运行)。 所以你可以这样做: 手表扩展代码: [[WCSession defaultSession] sendMessage:@{@"cmd":@"sendUpdate"} replyHandler:nil errorHandler:^{ /*handle errors*/ }] iOS应用代码: - (BOOL)application:(UIApplication *)application
  • 电源设置关闭后如何唤醒 Windows 显示器?(How do I wake up my Windows monitors once turned off by power settings?)
    问题 所以我的 Vista 机器设置为在 10 分钟后关闭它的显示器。 (注意:机器没有暂停,或休眠) 我有一个 .Net 应用程序正在运行,它需要在指定的时间“唤醒”系统。 作为人类,您只需移动鼠标或按下一个键即可。 我如何以编程方式执行此操作? 我试过:以编程方式设置光标; 使用“发送密钥”; 甚至调用 CreateWaitableTimer 以取消挂起(即使它没有挂起),希望这会触发某些事情。 理想情况下,用 c# 编写代码会很棒,但正确的 Win API 就足够了。 提前谢谢了。 回答1 您应该能够通过发送系统命令消息来控制监视器电源,如下所示。 请注意,这是在 XP 上测试的,Vista 可能会有所改变,因此您需要对其进行测试并告诉我们。 此代码在 VB 中,但您可以看到它使用的 Win32 API 调用。 您需要将窗口句柄传递给函数,因此您的代码将需要创建一个窗口来处理消息(只需将其传递给默认的窗口处理函数)。 Const SC_MONITORPOWER As Integer = &HF170 Const WM_SYSCOMMAND As Short = &H112S Private Function SendMessage( ByVal Handle As Int32, ByVal wMsg As Int32, ByVal wParam As Int32, ByVal
  • 使用 WatchConnectivity 获取核心数据请求(Core Data fetch request with WatchConnectivity)
    问题 我目前正在尝试将 CoreData 数据从我的 iOS 应用程序获取到 watchOS 扩展程序。 我正在使用 WatchConnectivity Framework 通过sendMessage(_ message: [String : Any], replyHandler: (([String : Any]) -> Void)?, errorHandler: ((Error) -> Void)? = nil)获取字典sendMessage(_ message: [String : Any], replyHandler: (([String : Any]) -> Void)?, errorHandler: ((Error) -> Void)? = nil)函数。 基本连接工作正常。 iOS 应用程序是可访问的,如果我尝试回复示例字典,一切正常。 到目前为止一切顺利,但是当我开始在后台对 iOS 应用程序执行获取请求时,Watch 应用程序从未收到数据。 过了一会儿,我收到了这个错误: Error while requesting data from iPhone: Error Domain=WCErrorDomain Code=7012 "Message reply took too long." UserInfo={NSLocalizedFailureReason