David Robertson David Robertson - 5 months ago 23
Swift Question

WatchKit app losing data after going background - Swift

I'm passing a dictionary from my iPhone to the watch using the (watchOS 2)

applicationContext
method.

Inside the iPhone app:

func giveMeInfo(){
var lastStringUsed = porkee288.storyPoints.last!
do {
let resultDict = ["dict": myDict]
try WCSession.defaultSession().updateApplicationContext(resultDict)
}
catch {
print("Something wrong happened")
}
}


Inside the watch app:

func session(session: WCSession, didReceiveApplicationContext applicationContext: [String : AnyObject]) {

dispatch_async(dispatch_get_main_queue()) { () -> Void in

if let retrievedDict = applicationContext["dict"] as? [String : String] {

self.dictInsideWatch = retrievedDict
}
}
}


The data is fetched by the
tableview
in the
watchKit
nicely, however, each time the app goes to the background, the data is automatically lost, which is strange because in iPhone apps dictionaries have some persistence (at least until becoming suspended).

What would you recommend to counteract this issue and keep the data from disappearing?

Answer

The problem you're describing is that the table doesn't show any data once you return to the watch app. Although you didn't show that specific code, it's likely due to the dictionary being blank the next time the app is opened.

Since the application context is only received once, any property observer or method you might be using to reload the table would only fire when the data is newly arrived, not when the app is resumed.

When your dictionary is blank, you can fall back on the receivedApplicationContext property to access the most recent received data for your table.

A dictionary containing the last update data received from a paired and active device. (read-only)

Use this method to access the most recently received update dictionary. The session object also sends a newly arrived dictionary to the session:didReceiveApplicationContext: method of its delegate.

You can also persist the dictionary in NSUserDefaults to handle the case when your app has been terminated while suspended.

You didn't show how you called loadTable() once you had the data. You definitely want to do that, once you've (received new data or) retrieved persisted data.

if !session.receivedApplicationContext.keys.isEmpty {
    // Use most recently received dictionary
    dictInsideWatch = receivedApplicationContext["dict"]
} else {
    // Use persisted dictionary
    dictInsideWatch = NSUserDefaults.standardUserDefaults().dictionaryForKey("dict") ?? [:]
}
loadTable()

If you adopt this approach, make sure to persist the data (either immediately after it's received, or at the point when the app is about to move to an inactive state).

Comments