如何从watchOS 2唤醒iPhone应用程序?

我的应用程序具有非常丰富的网络层,我的Apple Watch应用程序取决于所有型号。 不幸的是,该应用程序的模块化程度不足以在手表应用程序中提供此图层。

我通过使用openParentApplication解决了这个问题:唤醒iPhone应用程序,执行请求并返回结果。

在watchOS 2中,这种方法已经消失,我应该使用WatchConnectivity。 使用它的最佳方法是发送userInfo字典。

但是,如何唤醒iPhone应用程序来处理我的请求? 要获得有关新userInfos的通知,我必须使用WCSessionDelegate,为此我需要一个WCSession对象。 但是什么时候应该创造呢? 以及如何唤醒应用程序?

我问了一位Apple工程师,并得到了以下提示:iOS-App应该在后台任务中启动。 所以以下内容对我很有帮助:

UIApplication *application = [UIApplication sharedApplication]; __block UIBackgroundTaskIdentifier identifier = UIBackgroundTaskInvalid; dispatch_block_t endBlock = ^ { if (identifier != UIBackgroundTaskInvalid) { [application endBackgroundTask:identifier]; } identifier = UIBackgroundTaskInvalid; }; identifier = [application beginBackgroundTaskWithExpirationHandler:endBlock]; 

将此添加到您的session:didReceiveMessage:session:didReceiveMessageData:以三分钟超时启动后台任务的方法。

Swift版本的Benjamin Herzog的建议如下。 值得注意的是,虽然我确实选择将Watch启动的工作推送到后台任务,但只要我的应用程序在后台,系统就可以将其唤醒。 在后台任务中执行工作似乎不是必需的,但这是最佳实践。

 override init() { super.init() if WCSession.isSupported() { session = WCSession.defaultSession() session.delegate = self session.activateSession() } } func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0), { let taskID = self.beginBackgroundUpdateTask() //Do work here... self.endBackgroundUpdateTask(taskID) }) var replyValues = Dictionary() let status = "\(NSDate()): iPhone message: App received and processed a message: \(message)." print(status) replyValues["status"] = status replyHandler(replyValues) } func beginBackgroundUpdateTask() -> UIBackgroundTaskIdentifier { return UIApplication.sharedApplication().beginBackgroundTaskWithExpirationHandler({}) } func endBackgroundUpdateTask(taskID: UIBackgroundTaskIdentifier) { UIApplication.sharedApplication().endBackgroundTask(taskID) } 

在WatchKit扩展中,您将需要使用WatchConnectivity WCSession sendMessage API。 在扩展程序中检查iOS应用程序是否可访问,然后发送消息:

 let session = WCSession.defaultSession(); if session.reachable { let message = ["foo":"bar"] session.sendMessage(message, replyHandler: nil, errorHandler: { (error) -> Void in print("send failed with error \(error)") }) } 

此消息将导致系统在后台唤醒iOS应用程序,因此请确保在后台运行时调用的iOS应用程序代码中设置WCSession(例如:您不希望把它放在UIViewController的子类的viewDidLoad中,以便收到消息。 由于您将要求获取某些信息,因此您可能希望利用回复块。

因此,这就是您在后台启动iOS应用程序的方法,尽管WatchConnectivity WWDC会话建议尽可能使用“后台”传输方法。 如果您的手表应用程序是只读的,那么您应该能够使用后台传输在iOS设备上排队任何更改,然后它们将在下次运行时传送到手表应用程序。

Interesting Posts