Watch OS 2 - WCErrorCodeDeliveryFailed が出てiPhoneとWatchでデータのやり取りが出来ない時の対応

はじめに

Watch OS 2からは、Apple WatchがiPhoneアプリから独立して動くことになったので、これまでとは違った書き方が必要です。

この対応を行っている最中に、以下の様なエラーが出て詰まってしまったので、その備忘録を示します。

エラーの内容 WCErrorCodeDeliveryFailed

Watch Extension[3994:434267] [WC] -[WCSession _onqueue_notifyOfMessageError:messageID:withErrorHandler:] CFEDC3E4-FE0F-439D-B884-1CB2EC349DED errorHandler: YES with WCErrorCodeDeliveryFailed
Error Domain=WCErrorDomain Code=7014 "Payload could not be delivered." UserInfo={NSLocalizedDescription=Payload could not be delivered.}

実際に書いていたコードの中身

iPhone側、AppleDelegate

let wcSession = WCSession.default

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    initWCSession()
}
func initWCSession() {
    if WCSession.isSupported() {
        wcSession.delegate = self
        wcSession.activate()
        print("session activate")
    } else {
        print("session error")
    }
}

Watch Extension側

let wcSession = WCSession.default

override func awake(withContext context: Any?) {
    super.awake(withContext: context)
        
    // WCSessionの開始
    if WCSession.isSupported() {
        wcSession.delegate = self
        wcSession.activate()
            
        sendMessageToApp()
    }
        
}

func sendMessageToApp(){

    guard wcSession.isReachable else {
        return
    }

    print("sendMessageToParent()")
        
    let message = [ "toParent" : "OK" ]
        
    wcSession.sendMessage(message, replyHandler: { replyDict in
        print(replyDict)
    }, errorHandler: { error in
        print(error)
    })
}

今回上述しているエラーは、このprintで表示したエラーの中身です。

対応方法

今回の原因は、メッセージを受信する(iPhoneのAppDelegate側)方のレシーバーの処理が足りていませんでした。

AppDelegateに以下のメソッドを追加する事で、レシーバーがメッセージを受信できるようになるので、正常にデータを送信することができるようになります。

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
    replyHandler(["reply" : "OK"])
}