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
时出错