Why Sending Message from Watchkit Extension to iOS and Getting Back a Reply Is So Slow

Why sending message from WatchKit extension to iOS and getting back a reply is so slow?

AFAIK, when you send a message to other device, the message will be archived to file on local directory that called as WatchDirectory.

This directory will be synchronized to other device like as other iCloud Drive App or Drop Box through bluetooth. Because this approach doesn't need App running for iOS and watchOS App while the transfer will be finished.

When the new files were arrived on directory, iOS(or watchOS) will invoke WCSession related API to process content. If needed, iOS(or watchOS) will awake the destination App in background before dispatch message.

With watchOS1, the watch extension runs on iOS, only remote UI runs on AppleWatch. So it requires much more simple process to communicate, just communication between processes.

sendMessage is much more expensive method than other communication API those are provided by WCSession. iOS can't use it till the watch App runs foreground, And using sendMessage from watchOS should have to wake up iPhone and launch iOS App in background. After the dispatched messages were handled, iOS may kill the destination app that running on background to get memory back.

So, IMO there is no reason that it should be fast.

Watchkit: watchos2 reply from sendMessage is very slow

If you need to get an immediate reply from the other side, then sendMessageData with a replyHandler is the best you are going to find.

WCSession sendmessage is twice as slow after updating from 2.1 to 2.2

So, I was running tests today on the same piece of code, using the same devices, and although the code has not changed, it is now running twice as fast as it initially did (in 2.1). Logs are coming in the range of .12 - .2 seconds. Only thing that has happened since then is software updates. Also, the fail block is no longer called after 5 mins. So both parts of this question are magically working. I am currently using iOS 9.3.4(13G35) and watch is at 2.2.2. Seems to have been an OS issue somewhere in the chain of processing the queue between the watch and the phone. All is good now.

Inconsistent behaviour with WatchKit app - Swift

Multiple delegates/activations:

You're repeatedly setting up, delegating, and activating sessions in different parts of your app. You keep changing your delegate, so code in one part of the app will no longer be used after you delegated handling to a different part of your app.

You should use a single session/delegate throughout your app. One solution is to setup a WCSession singleton which would be available app-wide. Here's a guide which walks you through that process.

Only the most recent application context would get sent:

By trying to queue up multiple application context requests, the earlier ones would no longer be in the queue when the system gets around to transmitting it, as the system would have already replaced the preceding context with the later one. So only the last (dataArray3) would ever get transmitted.

Use the updateApplicationContext:error: method to communicate recent state information to the counterpart. When the counterpart wakes, it can use this information to update its own state. ... This method overwrites the previous data dictionary, so use this method when your app needs only the most recent data values.

If all of the arrays represent the recent state of your application, you want to transmit them together in a single dictionary.

var dataArray = [String: AnyObject]()
dataArray["somedata"] = array2d1
dataArray["somedata1"] = array2d2
dataArray["somedata2"] = array2d3
dataArray["somedata3"] = array2d4

do {
try session.updateApplicationContext(dataArray)
}
catch {
print(error)
}

It may also help to add some error handling to your sendMessage code, as the paired device may not always be reachable.

Slow communication:

As for the communication being too slow, there are two issues at hand.

  • Transfers may not happen immediately.

    When only one session is active, the active session may still send updates and transfer files, but those transfers happen opportunistically in the background.

    Remember that background transfers are not be delivered immediately. The system sends data as quickly as possible but transfers are not instantaneous, and the system may delay transfers slightly to improve power usage. Also, sending a large data file requires a commensurate amount of time to transmit the data to the other device and process it on the receiving side.

  • The more data you send, the longer it takes to transmit/receive it all.

    When sending messages, send only the data that your app needs. All transfers involve sending data wireless to the counterpart app, which consumes power. Rather than sending all of your data every time, send only the items that have changed.

You can control how much data you send, as well as whether the data is sent interactively or in the background. If the watch is reachable, you could use sendMessage for immediate communication. If it's not reachable, you could fall back on a background method.

WCSession sendMessage errorHandler called multiple times

I experienced the same problem a few months ago. The solution I came up with was using a variable to store the id I gave to the last request made, for instance

self.lastCallId = "watch_load_clients"

And if the matching id isn't received (I also send the id back) then I ignore the request.

I think it's just a Bluetooth issue.

Edit: Also, are you making requests and not receiving a response? That is the case when your problem should happen.

Debugging and state restoration concerns of WatchOS WCSession sendMessage waking killed iPhone app

Background and State Restoration:

Your app which was launched in the background (then terminated) will never save state, because it never transitions from foreground to background (which is when state preservation happens).

From Preserving and Restoring State:

UIKit preserves your app’s state at appropriate times, such as when your app moves from the foreground to the background.

The reason why it doesn't save state is because it is launched directly into the background.

From The App Life Cycle:

In addition, an app being launched directly into the background enters [the background state] instead of the inactive state.

Debugging an app launched in the background:

As for attaching to your app when it is launched in the background from a terminated state, there's a question which already provides the correct approach for this scenario.

If you have specific questions about that, please leave a comment with the author of that answer.



Related Topics



Leave a reply



Submit