简体   繁体   中英

Watch Connectivity works the first time but not after that

I've tested on the Simulator and Device, somehow Watch Connectivity stops working after it's used once.

I'm passing data from Watch -> iPhone, and it only works once and then stops after that.

Any ideas?

iPhone ViewController :

var session: WCSession?

override func viewDidLoad() {
    super.viewDidLoad()
    if WCSession.isSupported() {
        session = WCSession.default()
        session?.delegate = self
        session?.activate()
    }
}

func session(_ session: WCSession, didReceiveApplicationContext applicationContext: [String : Any]) {
    // Received Application Context from Watch
    let type = applicationContext["watchType"]
    print("Type iPhone: \(type)")

    DispatchQueue.main.async {
        self.type.text = "Type: \(type)"
    }

}

Watch InterfaceController :

let session = WCSession.default()

override func awake(withContext context: Any?) {
    super.awake(withContext: context)

    if WCSession.isSupported() {
        session.delegate = self
        session.activate()
    }
}

@IBAction func startPressed() {
    saveEverything()
}

func saveEverything() {
    let watchContextType = ["watchType" : "Boxing/Running"]

    do {
        print("Type Watch: \(watchContextType)")
        try session.updateApplicationContext(watchContextType)
    } catch {
        print("Didn't work")
    }
}

When you use the updateApplicationContext() , you need to change the parameters for each call, otherwise the msg will not be delivered. I belive this is to conserve battery.

Anyway, try sending your message using sendMessage() or sendMessageData() , then the messages get delivered each time, even when they have the same contents. And, they are higher priority than updateApplicationContext so it's win-win :)

Here is the documentation: https://developer.apple.com/library/content/documentation/General/Conceptual/WatchKitProgrammingGuide/SharingData.html#//apple_ref/doc/uid/TP40014969-CH29-SW1

If you want to Drain Battery of your apple watch app Quickly then above technique of @Jens is well and good.


Instead of shifting from updateApplicationContext() to sendMessage() better make small change in your project to get Desired result.


I will explain the question scenario and then solution along with Demo app :-

在此处输入图片说明

 @IBAction func sliderChange(_ value: Float)

{
    let str:String?
    switch value {
    case 0...7 :
          str = "Running"
    case 8...14 :
          str = "Sleeping"
    default:
        str = "normal"
    }
     updateContext(value: str!)
}

func updateContext(value:String) {
    let dictionary = [ "watchType" : value ]
    do {
        print("update application context is called do statemet")
        try session?.updateApplicationContext(dictionary)
    }
    catch{
        print("this is the catch statement")
    }
}

With update in slider Values in Watch ,iPhone values get updated .As you can see there is repetition of values for iPhone ie

When sliderValue are from 0 to 7 values remain "Running" && "Sleeping" for 8 to 14 .

App work fine if I varies values of slide and desired result is reflected in iPhone in normal scenario.

Scenrio where it fails :- i)Change the slider values from 0 to 3 then "Running" is reflected in iPhone. Thant's fine . ii)Now close the iPhone application then change the slider values from 3 to 5 no we can see real problem when iPhone is opened back. iii) Values is not triggered to iPhone .

在此处输入图片说明

Due to internal caching mechanism of updateApplicationContext() restrict to trigger of duplicate values to iPhone .

Store the last updated state in didReceiveApplicationContext() and display state according to stored value .

override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        checkStatus()
        updateSavedState()
    }
    func checkStatus() {
        print("check status")
        if WCSession.isSupported() {
            session = WCSession.default()
            session?.delegate = self
            session?.activate()
        }
    }

     func session(_ session: WCSession, didReceiveApplicationContext    applicationContext: [String : Any]) {
        let type = applicationContext["watchType"]!
         DispatchQueue.main.async {
            self.updateLabel.text =  " Type: \(type)"
            UserDefaults.standard.set(type, forKey: "savedState") //setObject
        }
    }

    func updateSavedState() {
        self.updateLabel.text = UserDefaults.standard.string(forKey: "savedState")
    }

Now everything is work perfect. Demo App .

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM