正在模拟器和真实物理设备iphone5s上进行测试。我试图使用WCSession sendMessage从WatchOS2扩展到iPhone iOS9代码进行通信。当iphone应用程序在前台和后台模式下运行时,它都能很好地工作。
但是如果我杀死iPhone应用程序(不运行应用程序),那么我总是得到errorHandler超时。所以Watch不能再和iPhone通信了。
"Error Domain=WCErrorDomain Code=7012 "Message reply too long."UserInfo={NSLocalizedDescription=消息回复时间过长。nslocalizedfailurerreason =应答超时。}".
我想它应该在后台唤醒iPhone应用。
你知道如何解决这个问题或修复它吗?谢谢你!
在AppDelegate
didFinishLaunchingWithOptions
方法中激活WCSession
是很重要的。你还必须把WCSessionDelegate
放在那里。如果你在其他地方这样做,当系统在后台启动被杀死的应用程序时,代码可能不会被执行。
同样,您应该通过replyHandler
发送回复。如果您尝试以其他方式发送,系统将等待永远不会出现的回复。因此出现了超时错误。
下面是一个例子,当应用程序被杀死时唤醒它:
设置会话。通常在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()
}
}
然后实现delegate方法发送回复给watch:
func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {
replyHandler(["message": "Hello Watch!"])
}
只要Watch和iPhone有连接,这个功能就可以工作。如果应用程序未运行,系统会在后台启动它。
我不知道系统是否等待足够长的时间,直到你从iCloud收到数据,但这个例子肯定会唤醒应用程序。
经过几个小时的尝试和@jeron的提示。我终于自己解决了这个问题。
在我的session:didReceiveMessage委托方法中,我有两个调用。1.replyHandler电话。2. 我有一个异步进程(RXPromise)在我的情况下运行,它嵌套了相当多的RXPromise回调从云服务中获取各种数据。我没有注意它,因为它应该打电话并立即返回。但现在我把RXPromise block都注释掉了,它每次都能在后台唤醒iOS应用。
最后我弄清楚麻烦是因为在RXPromise调用之后,它不再保证被着陆回主线程了。我相信session:didReceiveMessage必须在主线程上返回。我在苹果的文档中没有看到这一点。
最终解决方案:
- (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
将导致错误当应用程序被杀死