user8403747
user8403747

Reputation:

swift WatchConnectivity running in background - ApplicationContext is not running all the time

I want to know a better way to send (with iPhone) message to Watch (in background). Currently i use:

session.update(applicationContext: package, completion: nil)

for sending messages to Watch and

 func didReceivedApplicationContext(applicationContext:[String : Any])

to receive messages in Watch. The problem is that as is said in documentation "The system will transfer content at opportune times" and i can't control those "oportune times".

At this time, i check in iPhone class the state of Watch. If the Watch is on Background, i send data with updateApplicationcontext (which is not verry good), else, if Watch is on foreground, i send data with sendMessage

Code:

 if session.isWatchReachable()
    {
        session.send(message: package, completion: nil)
    }
    else
    {
        session.update(applicationContext: package, completion: nil)
    }

So is a better way to transfer data in background?

Upvotes: 1

Views: 2304

Answers (2)

Alexander Volkov
Alexander Volkov

Reputation: 8372

It's not possible to receive data on iWatch in background. You can only receive data in foreground. updateApplicationContext() method is designed especially for sending data in background (from iPhone to iWatch). When the watch app will be activated (opened) the context data will be available for usage - no need to worry.

15:43 - https://developer.apple.com/videos/play/wwdc2021/10003/

So, what you did in the answer is a correct solution.

Upvotes: -1

David Pasztor
David Pasztor

Reputation: 54706

Well you have to choose between background transfers and sending data immediately. Using the WatchConnectivity framework there is no way to schedule data transfer to happen at an exact moment in time.

You have to choose between using a method that can send data even while your app is in the background or sending data immediately from the foreground.

If you need a guarantee that the data will be transferred by the time your app wakes up from the background and for your use case updateApplicationContext proved to be insufficient during testing, you can use a workaround.

The workaround is to use updateApplicationContext to transfer data in the background and in your Watch app's ExtensionDelegate class, use the applicationDidBecomeActive() method to check whether the data transfer has happened in the background and if it did not happen, use the sendMessage function to request the data immediately from the other app and send back the requested data as a response.

To implement this, your function should look something like this on your Watch app:

func applicationDidBecomeActive(){
    if !haveReceivedData {  //Bool value that should be updated to true once data is received from the phone
        session.sendMessage(["Requesting data":True], replyHandler: {
            //parse the data, update the UI
        }, errorHandler: { error in
                    print("Error requesting data",error)
                })
    }
}

And on your iPhone app you do the following:

func session(_ session: WCSession, didReceiveMessage message: [String : Any], replyHandler: @escaping ([String : Any]) -> Void) {
        if let isRequestingData = message["Requesting data"] as? Bool, isRequestingData == true {
            replyHandler(["Requested data":data])
        }
    }

Upvotes: 0

Related Questions