这是在模拟器和真实物理设备iphone5s上进行测试的。我尝试使用WCSession sendMessage从WatchOS2扩展到iPhone iOS9代码进行通信。当iphone应用程序在前台和后台模式下运行时,它运行良好。
但如果我杀了iPhone应用程序(根本没有运行应用程序),那么我总是得到errorHandler超时。所以Watch再也无法与iPhone通信了。
“Error Domain = WCErrorDomain Code = 7012”消息回复花了太长时间。“ UserInfo = {NSLocalizedDescription =邮件回复花了太长时间。, NSLocalizedFailureReason =发生回复超时。}“。
我认为应该在后台唤醒iPhone应用程序。
知道如何解决这个问题或修复它?谢谢!
答案 0 :(得分:16)
在WCSession
AppDelegate
方法中激活didFinishLaunchingWithOptions
非常重要。你还必须在那里设置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 App中:
相同的会话设置,但这次也设置了委托:
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!"])
}
只要Watch和iPhone之间存在连接,此功能就可以使用。如果应用程序未运行,系统将在后台启动它。
我不知道系统是否会等到你从iCloud收到你的数据,但是这个例子肯定会唤醒应用程序。
答案 1 :(得分:9)
经过几个小时的尝试并从@jeron提示。我终于弄明白了这个问题。
在我的会话中:didReceiveMessage委托方法,我有两个调用。 1.replyHandler电话。 2.在我的情况下我运行了一个异步进程(RXPromise),它嵌套了很多RXPromise回调来从云服务中获取各种数据。我没有注意它,因为它应该立即呼叫并返回。但是现在我已经将RXPromise块一起注释掉,它每次都可以在后台唤醒iOS应用程序。
最后我弄清楚麻烦是因为在RXPromise调用之后,再也不能保证退回到主线程了。我相信session:didReceiveMessage必须在主线程上返回。我在Apple文档的任何地方都没有看到这一点。
最终解决方案:
- (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.....
});
}
答案 2 :(得分:0)
好吧,您可以使用transferUserInfo
来排队呼叫。使用sendMessage
会在应用被杀时导致错误