WatchOS2 WCSession sendMessage不会唤醒iPhone在后台

这是在模拟器和真实的物理设备iphone5s上进行testing。 我试图使用WCSession的sendMessage从WatchOS2扩展到iPhone的iOS9代码进行通信。 当iphone应用程序在前台和后台模式下运行时,它运行良好。

但是,如果我杀了iPhone应用程序(根本不运行应用程序),那么我总是得到errorHandler超时。 所以Watch不能再与iPhone通信。

“错误域= WCErrorDomain代码= 7012”消息回复花费了太长时间。“UserInfo = {NSLocalizedDescription =消息回复花了太长时间,NSLocalizedFailureReason =回复超时发生}”。

我认为它应该在后台唤醒iPhone应用程序。

任何想法什么解决这个问题或解决它? 谢谢!

AppDelegate didFinishLaunchingWithOptions方法中激活WCSession是非常重要的。 你也必须在那里设置WCSessionDelegate 。 如果你在别的地方做,当系统在后台启动杀死的应用程序时,代码可能不会被执行。

另外,你应该通过replyHandler发送回复。 如果您尝试发送其他信息,系统将等待一个永不回复的回复。 因此超时错误。

这是一个例子,如果它被杀死的话会唤醒应用程序:

在WatchExtension中:

安装会话。 通常在您的ExtensionDelegate中:

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

然后当你需要从应用程序中的东西发送消息:

 if WCSession.defaultSession().reachable { let messageDict = ["message": "hello iPhone!"] WCSession.defaultSession().sendMessage(messageDict, replyHandler: { (replyDict) -> Void in print(replyDict) }, errorHandler: { (error) -> Void in print(error) } } 

在iPhone应用程序中:

相同的会话设置,但这次也设置委托:

 func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { ... if WCSession.isSupported() { let session = WCSession.defaultSession() session.delegate = self session.activateSession() } } 

然后执行委托方法将回复发送给手表:

 func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { replyHandler(["message": "Hello Watch!"]) } 

只要手表和iPhone之间有连接就可以工作。 如果应用程序没有运行,系统将在后台启动它。

我不知道系统是否等待,直到您收到来自iCloud的数据,但这个例子肯定会唤醒应用程序。

经过几个小时的尝试,并从@jeron提示。 我终于自己想出了这个问题。

在我的会话中:didReceiveMessage委托方法,我有两个调用。 1.replyHandler电话。 2.我有一个asynchronous进程运行(RXPromise)在我的情况下,它嵌套了不lessRXPromisecallback从云服务获取各种数据。 我没有注意,因为它应该立即打电话给我。 但是现在我把RXPromise全部注释掉了,每次都可以在后台唤醒iOS应用程序。

最后我弄清楚这个麻烦是因为在RXPromise调用之后,再也不能保证返回到主线程了。 我相信session:didReceiveMessage必须在主线程上返回。 我没有看到苹果文档中提到的任何地方。

最终解决scheme

 - (void)session:(WCSession *)session didReceiveMessage:(NSDictionary<NSString *, id> *)message replyHandler:(void (^)(NSDictionary<NSString *, id> *_Nonnull))replyHandler { replyHandler(@{ @"schedule" : @"OK" }); dispatch_async(dispatch_get_main_queue(), ^{ Nested RXPromise calls..... }); } 

那么,你可以使用transferUserInfo为了排队的电话。 使用sendMessage将导致应用程序被sendMessage时出错