WatchOS2 WCSession sendMessage 不会在后台唤醒 iPhone



正在模拟器和真实物理设备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将导致错误当应用程序被杀死

最新更新