WatchConnectivity: Sharing The Latest Data via Application Context

Check out previous blog posts on WatchOS 2 if you haven’t already:

Background data transfers via Application Context should be done when your Watch App only needs to display the latest information available. For example, if your Glance shows the game score, the user doesn’t care that the score was 4-2 two minutes ago. They only care that the current score is 4-4. Another example for this use-case is a transportation app – your user doesn’t care that the last bus left the station five minutes ago – they only care about when the next bus will be arriving.

So the way Application Context works is that it queues up a piece of data, and if there’s a brand new piece of data available before the data is transferred, the original (old) data is replaced by the new data, which is then transferred over unless it is replaced yet again by an even newer piece of data.

Inspired by Kristina Thai’s Application Context tutorial, I’m going to walk through building a similar emoji-based app. In my app, the user selects a food emoji from a menu, and the latest food item is displayed by the Apple Watch app:



Note that in my app, I’m going to write more of an abstract data updating model than you’ll find in Kristina’s tutorial, so it’ll be over-engineered for the app I’m demoing.

The assumption I’m working with is that your actual app is going to be a lot bigger than this, and it’ll need to update several views or data sources with the data received from the iOS app (or the Watch app). So if your app is actually simple like the one I’m demoing, with only one view updating, Keep it Simple and check out Kristina’s tutorial!

I’m also playing around with different ways of doing the abstraction layer of sending the updated data to the different parts of the app that need it, so I’m sure there are better ways of doing it! If you think of any, let me know your thoughts in the comments.

The Setup

For this tutorial, I’m assuming you know how to create a Single View Application in Xcode, and create a simple Table View with a list of Food Emojis. If you’re having problems replicating it, take a look at my FoodSelectionViewController here.

I’m also assuming you know how to create a Watch App and do the basic styling in Interface.storyboard of your Watch Application. If you need help settings this up, make sure to read my WatchOS 2: Hello, World tutorial.

Finally, you should be able to set up the basic singleton to wrap around WCSession and activate it in application:didFinishLaunchingWithOptions in the AppDelegate and applicationDidFinishLaunching in the ExtensionDelegate in your Watch Extension. If not, take a look at my WatchConnectivity: Say Hello to WCSession tutorial.

You should have something that looks like this in your iOS app:

And something like this in your Watch App:

And of course, you can always refer to the source code for this tutorial if you ever need extra clarification.

Now, on to the fun stuff 🚀.

Sending Data

In my application, when the user selects a food item, it needs to be transferred in the background to my Watch App. That means the iOS app is the sender. This is super simple to do.

Just extend the WatchSessionManager singleton in your iOS app to update the application context:

So now, when the user selects a food item cell, you can call this method:

That’s it! The food item is now in a queue and will be send over to your Watch App, unless a new food item is selected before it gets transferred of course!

Receiving Data

Your Watch App now has to receive the data. This is pretty simple to start with. Just implement the session:didReceiveApplicationContext: WCSessionDelegate method.

Updating Data

Now that you received the data, this is the tricky part. Trying to let your Watch Extension’s InterfaceController and other views or data sources that your data has been updated. One way to do this is through NSNotificationCenter, but I’m going to try out a different approach. This is the part that can be done in multiple ways and is a bit over-engineered for this app, so keep this in mind.

Since we’re in Swift, my goal is to change to a value-type model as soon as I can. Unfortunately, as I mentioned in my blog post on WCSession, the WCSessionDelegate can only be implemented on an NSObject. So to mitigate that, I created a DataSource value that can take the applicationContext data, and convert it into something immutable and usable by multiple InterfaceControllers.

I can now set up a protocol that will update all parties that need to know about the data change with the most updated data source:

So now onto the interesting part! Your WatchSessionManager will need to somehow keep track of all the dataSourceChangedDelegates. This could be done through an array, and methods that will add and remove delegates from the array:

We can now add the implementation for when the application context is received:

Now, we just need to make sure our InterfaceController is DataSourceChangedDelegate, and is kept track of by the WatchSessionManager.

And that’s it!

You can view the full source code on Github here.

Note: A special thanks to @allonsykraken for reviewing my code and giving me some great ideas!

Enjoy the article? Join over 14,500+ Swift developers and enthusiasts who get my weekly updates.

  • Dave

    Hi Natasha.

    Fantastic post. Thank you!
    I am just starting out to learn watchOS 2 and your posts help me a lot.

    At the moment I am trying to build a simple table with data loaded from the network. Since watchOS supports NSURLSession now, I was wondering how you deal with loading data from the network.

    In all the examples I’ve seen, everyone seems to update the application context whenever data is updated in the main iOS app. Then lookup that data for display in the watch extension.

    My approach would be to check the last received application context. If there is no cached data, fire off a network request.

    What do you think? Would you recommend using NSURLSession or is relying on the application context sufficient?

  • Tessa

    I’m just a Swift/iOS/watch beginner so maybe I’m missing something- but why use an extension to a class that was user defined? Why not just add to the original class you made?

    • Mike Glukhov

      Single responsibility principle

  • Spock

    I have been trying out many samples for WatchKit. My Host App is in ObjectiveC and i am not inclined to write code in Swift. For watchOs2, i am not able to find good examples for my specific use case and most of the examples are in swift. Although, i am trying to understand the swift code and translating that into ObjectiveC, i am not able to find a perfect solution for my use case.
    I have 3 pages in my WatchApp. Now Each interface has to receive different data from the host app. Further, i have to have a user login check so that the app is redirected to a login splash screen asking the user to login in on the host app.
    So far, i have implemented the solution, but i am not sure whether this is the correct Approach.

    How can i achieve this with the example similar to the one in the blog?

    • Hajer Karoui

      Did you find anything useful in this context that’s written in objective C ?

  • Madhava Jay

    Great article, just wanted to point out something which was non-obvious and caused me a lot of wasted time debugging. If you DO NOT change the value of the payload you send in updateApplicationContext, the callback didReceiveUserInfo is not called. This probably makes perfect sense but if you missed the first one and you’re not looking for it you might think its not working.

  • Hajer Karoui

    Can you provide the code in objective C?
    great tutorial! This is what i have been looking for.