WCSession without activation

I am having a problem that the WatchKit session is not activated when I call the session.activateSession () method. This is the code I am using to set up the session.

if (WCSession.isSupported()) {
    session = WCSession.defaultSession()
    session.delegate = self // conforms to WCSessionDelegate
    session.activateSession()
    print("Session has been activated")
}

      

However, I put a breakpoint on the print line and when I inspect the session object, it says that the sessionActivated property is still false, even after the invoke function is invoked. I don't seem to have any error when I call invoke the session to be invoked, so I guess this should work, but it doesn't seem to be the case.

Also, if I try to use the sendMessage method on the session object later in my code like:

let message = ["request": "fireLocalNotification"]
session.sendMessage(
    message, replyHandler: { (replyMessage) -> Void in }) { (error) -> Void in
        print(error.localizedDescription)
    }

      

I am getting the error code "The operation could not be completed (WCErrorDomain error 7004.)" which I looked at which means "WCErrorCodeSessionNotActivated". This is another reason why I think the activation method is not working correctly. I even tried running the activSession method right before posting the message, but I still get the error. If anyone could explain what's going on it would be great, thanks! :)

+3


source to share


3 answers


You must activate a WatchConnectivity session for both the WatchKit Extension app and the iOS app. For example, you can do this in InterfaceController

override func awakeWithContext(context: AnyObject?) {
    super.awakeWithContext(context)
    if WCSession.isSupported() {
        let wcsession = WCSession.defaultSession()
        wcsession.delegate = self
        wcsession.activateSession()
        wcsession.sendMessage(["update": "list"], replyHandler: { (dict) -> Void in
            print("InterfaceController session response: \(dict)")
            }, errorHandler: { (error) -> Void in
                print("InterfaceController session error: \(error)")
        })
    }
}

      

and in AppDelegate



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

    if WCSession.isSupported() {
        let wcsession = WCSession.defaultSession()
        wcsession.delegate = self
        wcsession.activateSession()
    }

    return true
}

      

In a few examples I've noticed that people tend to set a delegate only on the class that handles requests, for example. if the watch were to send a message to the iOS app, the delegate would only be set in the iOS app. This is not true. As WatchConnectivity clearly indicates, you MUST set a delegate in both circumstances, otherwise you will get a 7004 error.

+3


source


Since "activateSession ()" is replaced by "activate ()" in Xcode 8, you need to add and extend for your class to delegate the session (WCSessionDelegate) and extend it with the function:

func session (_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: error?)

To ensure that the asynchronous "activate" method succeeds.



In your case:

extension  YourInterfaceControllerClass : WCSessionDelegate {

    func session(_ session: WCSession,
                 didReceiveMessage message: [String : Any],
                 replyHandler: @escaping ([String : Any]) -> Void)
    {
        //this function is mandatory and can be empty
    }

    func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?)
    {

       // Your code to be executed after asynchronous activation is completed:  
       let message = ["request": "fireLocalNotification"]
       session.sendMessage(
       message, replyHandler: { (replyMessage) -> Void in }) { (error) -> Void in
          print(error.localizedDescription)
    }

     //....

   }
}

      

+1


source


Are you using large numbers?

NSDictionary *userInfo = @{
                           @"a1":@(1000000000),   // 1000000000
                           @"a2":@(10000000000),  // 1e+10
                           @"a3":@(100000000000), // crash!
                           };
[[WCSession defaultSession] transferUserInfo:userInfo];

      

In the above code, the key value "a3" is dangerous, it will crash the Apple Watch.

Once you submit the list, it stays on Apple Watch until you reinstall the viewing app.

(This crash happens on the device, not on the simulator)

0


source







All Articles