2015-10-14 15 views
12

これはSimulatorと実際の物理デバイスiphone5でテストされています。 WatchS2の拡張機能からiPhoneのiOS9コードへの通信にWCSession sendMessageを使用しようとしました。 iphoneアプリがフォアグラウンドモードとバックグラウンドモードのいずれかで動作しているときにうまく動作します。WatchOS2 WCSession sendMessageはバックグラウンドでiPhoneを起動させません

しかし、私はiPhoneアプリを(すべてのアプリケーションを実行していない)殺すと、私はいつもerrorHandlerのタイムアウトを得ました。だからウォッチはもうiPhoneと通信できません。

"エラードメイン= WCErrorDomainコード= 7012 "メッセージの返信が長すぎました。" のUserInfo = {NSLocalizedDescription =メッセージの返信が長すぎました。、 NSLocalizedFailureReason =応答タイムアウトが発生しました。}"。

私はバックグラウンドでiPhoneアプリを目覚めさせると思います。

この問題を回避するにはどうすればよいですか、それを修正してください。ありがとうございました!

+0

iOSアプリのコードで、あなたがWCSessionを設定していますか? – ccjensen

+0

AppDelegate -initメソッドで設定しました。私はそれがUIViewControllerまたはinitのright viewDidLoadする必要があると思った? –

+0

さて、それはうまく聞こえます。あなたが送っているメッセージはかなり小さいと思いますか?もしそうなら、すべてのコードなしで何が間違っているのかを言うのは難しいです。 Appleにバグを報告するのはどうですか? – ccjensen

答えて

9

@jeronから試してヒントを得た後、私はついに自分自身で問題を理解しました。

私のセッションでは:didReceiveMessageデリゲートメソッド、私は2つの呼び出しがあります。 1.replyHandlerコール。私のケースでは、非同期プロセス(RXPromise)を実行しています。クラウドサービスからさまざまなデータを取得するためにかなりの数のRXPromiseコールバックをネストしました。私はそれに注意を払っていませんでした。なぜなら、すぐに電話して戻ってくるはずだからです。しかし、今度は私がRXPromiseブロックをまとめてコメントアウトしたので、毎回iOSアプリをバックグラウンドで起動することができます。

最後に、私は、RXPromise呼び出しの後、メインスレッドにもう戻ってくることを保証していないからです。そして、私はセッション: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..... 
    }); 

} 
+0

こんにちは@Frank、それはドキュメントがスレッドの問題を言及していないことはまったく正しいわけではありません。 WCSessionDelegateのヘッダーコメントは、デリゲートコールバックがシリアルバックグラウンドキューで発生することを指定しているため、main_queueに切り替える必要がありますが、他のすべての情報は便利で正しいものです。 – BootMaker

+0

@BootMakerああ、情報のおかげで。私は見てみましょう。 –

0

まあ、transferUserInfoを使用して呼び出しをキューに入れることができます。 sendMessageを使用すると、アプリケーションが終了したときにエラーが発生する

+0

私の目標は実際にはiPhoneからCloudからデータを取得することです。さまざまな理由から、WatchExtensionのNSUrlSessionを直接使用することはできません。したがって、sendmessageがiPhoneを起動し、クラウドからデータを要求し、次にtransferUserInfoを使用してデータをWatchに送り返します。 –

13

AppDelegatedidFinishLaunchingWithOptionsメソッドでWCSessionを有効にすることが重要です。また、WCSessionDelegateを設定する必要があります。他の場所で実行すると、システムがバックグラウンドで終了したアプリを起動したときにコードが実行されないことがあります。

また、返信はreplyHandlerで送信することになっています。あなたが他の何かを送信しようとすると、システムは決して来ない返答を待つ。したがって、タイムアウトエラー。ここで

は、それが殺されている場合、アプリをウェイクアップ例です。WatchExtensionで

セットアップセッション。その後、

func applicationDidFinishLaunching() { 
    if WCSession.isSupported() { 
     let session = WCSession.defaultSession() 
     session.delegate = self 
     session.activateSession() 
    } 
} 

そして、あなたはアプリから何か必要なときにメッセージを送信します:iPhoneアプリで

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) 
    } 
} 

同じセッションのセットアップを、今回は一般的にあなたのExtensionDelegateで代議員を設定する:

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からデータを受け取るまでシステムが十分に待機するかどうかはわかりませんが、この例では明らかにアプリケーションを起動します。

+0

ありがとうJoann、私は上のあなたの方法を正確に試みた。 iOSアプリはまだバックグラウンドで起動しません。 iOSアプリを開くとすぐに、すべてが再び機能し始めます。あなたはあなたのiOSアプリを殺そうとしましたが、それが動作しているかどうかを見るために時計を試しましたか? –

+1

はい、私はそれを試みましたが、アプリが殺されたとしても返事があります。 – joern

+0

短いテキストを送信したり、iCloudから何かを取得したりしてみましたか? – joern

関連する問題