WCSession Failing to Activate

蓝咒 提交于 2021-01-27 07:26:15

问题


I am having a problem with the WatchKit Connectivity Session failing to activate 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 have placed a breakpoint on the print line and when I inspect the session object, it says the sessionActivated property is still false, even after calling activateSession. I don't appear to be getting any sort of bug when I call activate session, so I assume it should have worked, but this does not seem to be the case.

Furthermore, if I try and use the sendMessage method on the session object later in my code like this -

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

I receive an error code "The operation couldn’t be completed. (WCErrorDomain error 7004.)" which I looked up which means "WCErrorCodeSessionNotActivated." This is yet another reason why I think the activateSession method isn't calling correctly. I have even tried running the activateSession method the line directly before I send the message, but I still receive the error. If anyone could help explain what is going on, that would be wonderful, thank you! :)


回答1:


You should activate the WatchConnectivity session on both the WatchKit Extension and the iOS app target. For example you might do it in the InterfaceController's

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 the AppDelegate

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

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

    return true
}

What I have noticed in several examples is that people tend to set a delegate only in the class which handles requests, e.g. if the watch was to send a message to the iOS app a delegate would only be set in the iOS app. This is WRONG. As the WatchConnectivity clearly states, you MUST set the delegate in both circumstances, otherwise you'll get the 7004 error.




回答2:


Since "activateSession()" changed to "activate()" in Xcode 8 ,You need to add and extension for your class to delegate the session ( WCSessionDelegate ), and extend it with the function:

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

In order to ensure that the asynchronous method "activate" finishes successfully.

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

     //....

   }
}



回答3:


Are you using big number values?

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

On the above code, the value of key "a3" is dangerous, it causes Apple Watch crash.

Once you send the list, it remains in Apple Watch until reinstall the watch app.

(This crash occurs on a device, not on a simulator)



来源:https://stackoverflow.com/questions/31191296/wcsession-failing-to-activate

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!