I have an iPhone app that sends data from the iPhone app directly to the watch face to be displayed as a complication.
I use the WatchConnectivity
framework to create a WCSession
to send the data to the watch from the phone.
My data is stored in a dictionary, and sent to the watch using WCSession
's transferCurrentComplicationUserInfo
method. (This method can be used something like 50 times a day, and I am aware of this - that is not the issue.)
The transferCurrentComplicationUserInfo
method seems to work the first time that I attempt to send data.
My problem is that my iPhone app is meant to call this function several times in a session, and it only reliably works the first time.
When I send a second set of data, the first set remains on the complication. Often, when I send the third set, the second set appears. Sometimes the second set appears permanently, and sometimes it only appears for a brief second before displaying the third set.
It is inconsistent, and that is the issue I am having.
Is there anything that I have set up incorrectly?
Code:
//iPhone code to send data to Apple Watch:
func sendComplication(complication: Complication) {
guard let session = session else {
delegate?.failedToSendComplication(reason: "Could not connect to your Apple Watch.")
return
}
guard let context = convertComplicationToDictionary(complication: complication) else {
delegate?.failedToSendComplication(reason: "Couldn't cast complication to a dictionary.")
return
}
if session.remainingComplicationUserInfoTransfers > 0 {
session.transferCurrentComplicationUserInfo(context)
delegate?.didSendComplication()
} else {
delegate?.failedToSendComplication(reason: "Due to hardware limitations, you can only send a certain amount of complications in a day. You have exceeded that limit for today. You can still set complications from the Apple Watch app.")
}
}
// WatchKit Extension Delegate to receive and handle data sent from iPhone app
import WatchKit
import WatchConnectivity
class ExtensionDelegate: NSObject, WKExtensionDelegate {
var session: WCSession?
override init() {
super.init()
self.session = newWatchConnectivitySession()
}
func newWatchConnectivitySession() -> WCSession? {
if WCSession.isSupported() {
let session = WCSession.default
session.delegate = self
session.activate()
return session
}
return nil
}
func reloadComplicationTimeline() {
let server = CLKComplicationServer.sharedInstance()
guard let activeComplicationFamilies = server.activeComplications else { return }
for comp in activeComplicationFamilies {
server.reloadTimeline(for: comp)
}
}
}
extension ExtensionDelegate: WCSessionDelegate {
func sessionReachabilityDidChange(_ session: WCSession) {
if session.activationState != .activated {
self.session = newWatchConnectivitySession()
}
}
// Receive info from iPhone app
func session(_ session: WCSession, didReceiveUserInfo userInfo: [String : Any] = [:]) {
// Parse dictionary and update data source
reloadComplicationTimeline()
}
func session(_ session: WCSession, activationDidCompleteWith activationState: WCSessionActivationState, error: Error?) {
guard let error = error else { return }
print(error.localizedDescription)
}
}
// UPDATE //
Upon further inspection, I now see that steps are happening out of order.
This is the sequence of events:
sendComplication
is called from the iPhone appExtensionDelegate
is initialized on the Watch app, setting up the WCSession
WCSession
receives the new data)WCSession didReceiveUserInfo
delegate method is called, data is parsed, and the data source is updated (too late)Resetting the iPhone, Apple Watch, and Mac fixed the problem.