Non-Obvious Things You Should Know When Starting Your First Apple Watch App
So you want to write a Watch app? When I was writing one a couple months ago, I discovered that there are some high-level gotchas that can trip you up. Mostly what it comes down to is, if you don’t understand the paradigm that Apple expects you to work within, you’re gonna have a bad time.
The Architecture
Probably the most important thing for you to internalize is what the major components of a Watch app are:
The Host iOS App
This is your regular app for the iPhone. Yes, you must still have one of these! You can’t write an app only for the Watch (at least at this point). It must be bundled with a regular iOS app.
The WatchKit Extension
This is a separate bundle of code (in fact, a target within your Xcode project). It gets packaged with your iOS app for distribution. However, it runs in a different process than your iOS app. This means that, for all practical purposes, you should think of it as a separate app.
The extension is responsible for getting whatever data is necessary, and using it to fill in the fields of the Watch UI. It also responds to user actions initiated from the WatchKit App.
The WatchKit App
This is the only part that actually runs on the Watch itself. It consists solely of user interface elements (XIBs, images, other resources). You cannot write any code that actually runs on the Watch. When the WatchKit app needs data or receives user input, it communicates with the WatchKit Extension via Bluetooth. (Don’t worry, the complexity of that communication is hidden from you.) So while it seems like you are directly interacting with the UI (like you would in an iOS app), that is not actually the case.
Interaction Between The Components
In a word, it’s limited. From the WatchKit Extension, you will receive requests from the WatchKit app. In return, the extension can set properties on the WatchKit app UI elements to update them.
The extension is also able to send a request for the Host app to be woken up in the background on the iPhone to complete a task, and return data to the extension. After that the phone app is suspended, never having been shown on the phone screen.
That’s about it. This means that from the Watch, the user cannot cause the iPhone app to appear on the phone. Nor can they go into the phone app and cause the WatchKit app to become active. That’s just not how Apple intends WatchKit apps to be used. The WatchKit app is meant to be a simplified view into the user’s data from your main app, designed to fit on this smaller screen.
How The User Launches Your WatchKit App
It’s important to remember that when the user looks at their Watch, they aren’t immediately going to see your app. They have to explicitly launch it. I don’t think Apple has clarified this yet, but I suspect that this will even happen if the user is using your WatchKit app, and then lowers their wrist for some number of seconds. When they look again, your app will probably have been closed.
There are three ways a user can launch your app:
Directly – By default, when the user looks at their Watch, they’ll see the Home screen. AKA, the giant blob of tiny icons. They can locate the icon for your app (hopefully), and tap to launch it directly.
Glances – You can optionally include a Glance interface in your WatchKit app. It is a single screen interface that does not accept any user input. It’s meant to be a quick “glance” at currently relevant information. Such as the current temperature, or the boarding pass for their next flight. If the user taps on the Glance, your WatchKit app is launched. Glances are accessed by swiping up from the bottom of the Watch screen.
Notifications – When the phone receives a notification, iOS determines (through some algorithm) if that notification should be shown on the Watch. If it is, and the user taps on it, your WatchKit app will be launched.
Other Limitations
You can’t really get any sensor data from the Watch, like accelerometer or anything like that. Also, you can’t make custom UI controls. There is no concept of touch events on the Watch, so you can’t make your own gestures or widgets. You’re basically stuck with the controls they provide (buttons, switches, sliders).
Indirect Communication
There are some arms-length methods for communicating between the phone app and the Watch app.
Notifications
This is one that gets a lot of people at first:
Anyone else have issues with #CoreData contextdidsave notifications not getting recvd in app extensions? #iOS
— Jerica (@JericaLurve) March 20, 2015
Regular NSNotifications will not pass between the Host app and the WatchKit Extension, because they are running in two separate processes. However, there is a way to send Darwin “notifications” between processes. I have some sample code you can check out. An important caveat is that these Darwin notifications are not able to carry any data other than the name of the notification. So how can you pass data?
Shared Filesystems via App Groups
You can create an “app group” shared by both apps, which is essentially a shared filesystem. It’s a bit of a pain to set up, since you need to configure them in the iOS Developer Portal, and then adjust your App IDs accordingly. But it’s worth it, since it is by far the most efficient way to share data between the phone and the Watch. Once you’ve got it setup, you can place Core Data databases in the shared filesystem. Or any kind of file, as long as you implement the necessary protocols (though I’ve heard that’s a bit tricky). If you want to share relative small, simple pieces of data, you might be best off just using NSUserDefaults. Though you must use it in conjunction with the App Group, since the standard NSUserDefaults instance is also not shared between the apps.
I hope that was helpful, and you don’t have to muddle through the basics like I did.
Non-Obvious Things You Should Know When Starting Your First Apple Watch App