Error: "Message reply took too long" - WCSession Watch OS2
Asked Answered
H

2

6

So I am using Watch Connectivity to request an array from the iPhone to the Watch.

The idea was to sendMessage from the watch, and the iPhone will reply with the array within the didReceiveMessage method.

However the iPhone does not seem to be responding, I thought the iPhone would open the application when I send the message from the Watch. I have tried even opening the application when I sendMessage but still no luck. When I wait long enough I get the following error message:

Error Domain=WCErrorDomain Code=7012 "Message reply took too long." UserInfo={NSLocalizedDescription=Message reply took too long., NSLocalizedFailureReason=Reply timeout occured.}

Does anybody know where I may be going wrong ?

Apple Watch

import WatchKit
import Foundation
import CoreData
import WatchConnectivity

class BookmarkedInterfaceController: WKInterfaceController, WCSessionDelegate {

var session : WCSession!
var objects: [AnyObject]!

@IBOutlet var table: WKInterfaceTable!

override func willActivate() {
    super.willActivate()
    //Check if session is supported and Activate
    if (WCSession.isSupported()) {
        session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
    sendMessageToIphone()
}
func sendMessageToIphone() {
    if WCSession.defaultSession().reachable {

        print("WCSession is reachabe")

        let messageDict = ["Request": "iPhone Can You Give Me The Array"]
        WCSession.defaultSession().sendMessage(messageDict, replyHandler: { (replyDict) -> Void in
            print(replyDict)
            }, errorHandler: { (error) -> Void in
                print(error)
        })
    }
}

func session(session: WCSession, didReceiveMessage message: [String : AnyObject]) {
   //recieving message from iphone
    print("recieved message from iphone \(message)")

    objects.append(message["Array"]!)

    print("Objects array = \(objects)")        
}

The console outputs

WCSession is reachabe Array nil

iPhone App Delegate

import UIKit
import CoreData
import WatchConnectivity

@UIApplicationMain

class AppDelegate: UIResponder, UIApplicationDelegate, WCSessionDelegate {

var window: UIWindow?
var session : WCSession!

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {

    //Check if session is supported and Activate
    if (WCSession.isSupported()) {
        session = WCSession.defaultSession()
        session.delegate = self
        session.activateSession()
    }
}

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {

    print("did recieve message from Watch")

    let applicationData = ["Array":["One", "Two", "Three"]]

    replyHandler(applicationData)

}

Nothing from the iPhone is being executed. Even when I manually open the app.

Hoon answered 2/2, 2016 at 18:15 Comment(2)
Your code looks fine to me. Just one question, you are using the same dummy data (["Array":["One", "Two", "Three"]]), right? Because if you have some other code block running to send back the actual data then there might be some other issue entirely. E.g. An array of custom objects can not be communicated back to Watch App like this.Emilio
@Emilio I was going to practice with an array of strings first that was sent and printed within the WCSession functions. My aim was to send an array of NSManagedObject's to the Watch to display in the table. So basically the reply handler on the phone would send the dictionary with and array of objects to the watch. Really weird how I cannot get the phone to respond :/ Might update Xcode with the new release and hope for the bestHoon
R
3

If you want the reply to the message the watch sent to contain the requested data, you should change your code to the following:

Watch

func sendMessageToIphone() {
    if WCSession.defaultSession().reachable {

        print("WCSession is reachabe")

        let messageDict = ["Request": "iPhone Can You Give Me The Array"]
        WCSession.defaultSession().sendMessage(messageDict, replyHandler: { (replyDict) -> Void in
            print("Array \(replyDict["array"])")
            }, errorHandler: { (error) -> Void in
                print(error)
        })
    }
}

Phone

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {

    print("did recieve message from Watch")

    let applicationData = ["Array":["One", "Two", "Three"]]

    //If identifier from recievedMessage is for Objects

    replyHandler(applicationData)

}

And separately, the reason why the sendMessage from the phone is not received by the watch is because you've implemented the wrong delegate method for the sendMessage invocation you are using.

If you call sendMessage with a nil replyHandler then this delegate method will be invoked on the receiving side: func session(session: WCSession, didReceiveMessage message: [String : AnyObject])

If you call sendMessage with a non-nil replyHandler then this delegate method will be invoked on the receiving side: func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void)

Referee answered 3/2, 2016 at 6:41 Comment(2)
Thank you for replying, so I changed the code to what you suggested, sorry I am unsure what you are saying about the receiving the message on the watch from iPhone. Are you saying I should be changing func session(session: WCSession, didReceiveMessage message: [String : AnyObject]) { print("recieved message from iphone \(message)") } ? Also with he current updates the I get the following output in the console.WCSession is reachable Array nil Program ended with exit code: 0Hoon
weird; maybe try changing print("Array \(replyDict["array"])") to print("replyDict \(replyDict)")Referee
R
0

You must activate the session before sending the message .Also you must set the delegate before you activate the session because you may lose some pending messages.

iphone side :

import UIKit
import WatchConnectivity

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, WCSessionDelegate {

var window: UIWindow?
var session : WCSession!

func session(session: WCSession, didReceiveMessage message: [String : AnyObject], replyHandler: ([String : AnyObject]) -> Void) {

    print("did recieve message from Watch")
    let applicationData = ["Array":["One", "Two", "Three"]]

    //If identifier from recievedMessage is for Objects
    session.sendMessage(applicationData, replyHandler: { reply in
        print("Got reply: \(reply)")
        }, errorHandler: { error in
            print("error: \(error)")
    })
}

func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    session = WCSession.defaultSession()
    session.delegate = self
    session.activateSession()
    return true
}
}

iWatch extension InterfaceController You must activate the session in the interface controller willactivate method.

import WatchKit
import Foundation
import WatchConnectivity

class InterfaceController: WKInterfaceController, WCSessionDelegate {

var session : WCSession!
var objects: [AnyObject]!

override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)

    // Configure interface objects here.
}
override func willActivate() {
    // This method is called when watch view controller is about to be visible to user
    super.willActivate()
    session = WCSession.defaultSession()
    session.delegate = self
    session.activateSession()
    objects = []
    sendMessageToIphone()
}

override func didDeactivate() {
    // This method is called when watch view controller is no longer visible
    super.didDeactivate()
}

func sendMessageToIphone() {
    if WCSession.defaultSession().reachable{

        print("WCSession is reachabe")

        let messageDict = ["Request": "iPhone Can You Give Me The Array"]
        WCSession.defaultSession().sendMessage(messageDict, replyHandler: { (replyDict) -> Void in
            print(replyDict)
            }, errorHandler: { (error) -> Void in
                print(error)
        })
    }
}

func session(session: WCSession, didReceiveMessage message: [String : AnyObject]) {
    //recieving message from iphone
    print("recieved message from iphone \(message)")

    objects.append(message["Array"]!)

    print("Objects array = \(objects)")
}
}

Note. Run the iphone application first. Then Run the extension and keep the iphone app in foreground.

Romanism answered 5/2, 2016 at 11:18 Comment(2)
Sorry I have updated my question with the full code, I had already activated the session and set the delegate.Hoon
@JKSDEV On the Watch side : You have not initialized objects array. Please create empty array objects = [] in willActivate method.Romanism

© 2022 - 2024 — McMap. All rights reserved.