The newest family of iOS is almost ready for release, and it’s been made available to developers for awhile now. If you’ve been out of the loop with WatchKit, it’s certainly not too late to get started. The API is friendly and familiar, and any seasoned iOS developer should be able to identify the big ideas quickly. This week, we’ll spend our time taking a look at those big ideas one by one.
Under the hood: Apple Watch Extension
So how does Watchkit work? Well, the first thing to know is that you don’t (yet) make a single apple watch app. Instead, they are an extension to an existing iOS app. So, like a widget, you add a new target to your project.
It suspiciously resembles an entire project in terms of components. Out of the box it’ll have an image.xcassets folder, .plist file, and more. Still, make no mistake, this is just an extension. That also means you have all the limitations that an extension inherently brings with it.
Your iOS app will house your data, and then in turn share it with your watch extension. An inviting location for this is NSUserDefaults. Setting up an App Group in your project will be necessary should you choose this route.
Once you have a suite name set up, NSUserDefaults can be used with initWithSuiteName: to share those values back and forth. If you are using core data, then a shared container would be your chosen technique.
If you are wanting to share code between a project and an extension, then you’ll have to grow up and become a real programmer. As it stands now, creating your own framework is the only way to do this. At this point, it’s a good idea to pursue that because you might have already needed one for a widget. Now, with Apple Watch, iOS has given us another reason to do so.
Breaking down the Extension
An apple watch extension gives you three ways to present information. Those are the Apple Watch, App Glances, and Notifications.
The apple watch app is the beating heart of the extension. From it, you’re going to be utilizing the other two components: glances and notifications. You don’t have to use notifications or glances, but as you’ll see later, they are insightful and elegant. You’d be missing out if you didn’t.
Glances are accessed when the user swipes up from the apple watch homescreen. They show quick tidbits of information that act as a springboard to launching the app. In the image below, you can see all of those pieces. From left to right: The app (more accurately, the home screen with apps), a glance, and notification.
Glances are the ambitious younger brother of the today widget for iPhone. They are to be snappy and lightweight. You want the user to get instant satisfaction. If executed correctly, the user will be provoked into jumping straight into your app to learn more.
Best of all, they are easily configured from the templates Xcode gives you. Of all the components of a watch extension, these are the most simple and intentional.
Each glance is managed by a WKInterfaceController object. This is mostly for just retrieving data inside the willActivate method and ensuring everything is current.
They require blind devotion on your part, as you don’t have control over how much time will lapse in between these calls. If you’ve made a widget, this setup is akin to the widget completion handler inside of the NCWidgetProviding protocol.
Interactive controls are not meant to be here. You also have very limited space, so the use of tables or maps is not advised. Make sure you code this to be as generic as possible, each apple watch app only gets to use one glance controller — so make sure it works for whatever message you are trying to convey.
This component will be a welcoming home to all local or remote notifications. They exist as two unique embodiments: short look and long look. The short look is configured, from top to bottom, with the icon, title, and the app name.
The long look, however, takes some risks and has a little more pizazz to it. When a notification comes to the apple watch, it starts out life as the short look notification. If the user decides they want to know more (i.e. by lifting up their wrist and looking at it), the long look replaces it. It’s UI allows for more detailed information, and it presents itself as such:
You’ll want to make a WKUserNotificationInterfaceController subclass to manage the UI — but not to handle the actions taken. Those are managed by a UIUserNotificationAction and fire off either as a foreground or background action.
You’ve seen like patterns before if you’ve ventured into Cocoa Touch. If the notification is in the foreground, the apple watch app handles it. If it goes in the background, then it’s up to the containing iOS app to take over and process it studiously and responsibly.
Apple Watch User Interface
By the way of controls, a lot is there that will be recognizable right away. UISwitches, UILabels and the like are all used and function like their iPhone counterparts. A big caveat, though, is that the UI cannot change at run time. When your watch app is launched, it does so diligently (and stubbornly) with the UI specified at design time.
That means you can’t remove, add, or relatively change anything once it’s up and running. You can manipulate values of those components, however. For example, you can mutate the hidden property or the alpha values. Caveats abound — when you hide a component it will surrender it’s space in the UI to be filled by another element. Conversely, assigning the alpha to 0 just renders it as invisible — still retaining it’s space.
The way the UI is laid out is fundamentally different than iOS apps. In iOS apps, you think in coordinates or (hopefully — using auto layout) you describe a relationship. With apple watch, the whole UI flows downwards, and each component will fill the available space.
You also have the option to design in a horizontal manner. You do have control over margin and spacing, but you aren’t going to be animating views or plunking a component right in the middle of the screen by using CGRectMake().
In a lot of ways, it harkens back to web design or thinking in grids like you would with bootstrap, foundation, or the newest grid based front end flavor of the week. To give you some flexibility, a useful new control called the WKInterfaceGroup can be called upon for nesting rows or otherwise laying things out in a more advanced fashion.
These newcomers act as “containers” to house other UI elements. In addition, you can give these groups a custom background image or color. There are also separators for segmenting out data and putting components in a sensible configuration that is sure to delight end users.
New UI Controls
Speaking of new UI controls for the apple watch — there are several. What you’ll find, and likely already surmised, is that a lot of them relate back to UIKit counterparts.
For instance, the WKInterfaceTable is a table view for all intents and purposes. You’ll want to use this for showing dynamic content by setting up a RowController object (otherwise known as a table cell). Inside interface builder you can assign the rows a unique identifier and also a custom class for hooking up outlets.
In what is sure to be a fan favorite, we now come to the WKInterfaceMap. This shows a small geographical location, it’s relatable to the map that you’d see on the iPhone — but zoomed in quite a bit.
One thing to be made aware of is that it isn’t interactive. In fact, it pings your iPhone to grab the snapshot of what the user will eventually see on the apple watch. That means no zooming or panning.
You can add up to five annotations on the map. If you want, you can supply a custom image for the annotation. If you don’t, watchkit will supply the default red pin.
These UI elements keep the same design patterns for use in a code base like UIKit. You still hook up outlets, and you still use the target-action design pattern. It’s most certainly no surprise, but it’s nice to know Apple has kept things simple so eager developers can begin contributing on day one without making past knowledge be bygones.
I mentioned hooking up outlets, so you probably assumed the endpoint was a open-armed view controller. Yes and no. As mentioned earlier, the view controller for an apple watch app is theWKInterfaceController. This will manage one screen of context.
It has one big difference between a regular UIViewController from UIKit in that it doesn’t really manage any actual views.
It will, however, run your app watch extension and manage the behavior of your interface remotely. Using the target-action pattern, the UI elements themselves respond to a given interaction.
With that said, here is a quick look at how an apple watch app is created.
- First — it launches on the apple watch.
- The extension awakes on the containing iOS app.
- The initial WKInterfaceController loads along with the storyboard inside the bundle.
- initWithContext: is called. Here, a UI with initial values is supplied and variables are assigned sensible values.
- willActivate: continues the journey, which means your app is getting displayed on the screen. Any last minute configuarations you might need to do will be done now or forever lost at this point.
- didDeactivate: happens - the app is no longer on the screen. Soon, it’ll be suspended and when it returns from this method, it’ll be deallocated. So, close your in flight tasks and take care of save state because in seconds it will be but a mere whisper, and henceforth eliminated from the heap.
Other Important Info
Navigation runs a little different in these lands. There are essentially two forms of navigation, you can either go hierarchical or page based.
Hierarchical resembles a navigation controller. Here, you push and pop a WKInterfaceController to progress through your watch app. The method signatures look the same too, behold: pushControllerWithName:Context:.
With this approach, you aren’t tied down to a fixed number of controllers to deal with, unlike page based navigation.
With page based navigation, things flow like a page controller on an iPhone. The views are specified at design time, so you will always have a fixed number of pages to present. The user swipes left and right and you’ll get the pager at the bottom for free.
The pager in question displays the number of pages you specified at design time. In any watch app — you’ll need to choose one of these two methods to navigate. You can’t use both. On top of those two core methods — you can bring up a view modally as well.
Debugging is relatively painless. To do so, just select your watch app scheme at the top of Xcode, much like you would a today widget. When your app begins to run in the simulator, you’ll want to choose hardware — external display — apple watch.
That’ll pop up a little screen to mimic the dimensions of an apple watch. You can also debug your notifications too. To do so, just include a supportnotification.json file in your bundle to get started.
Some other random/notable things:
One can use the Handoff API to utilize deep linking to pass notifications and info to controllers. Animations also go old school. To do it, you’ll have to iterate over an array of images. There’s an image cache available to use — with a ceiling of 20 mb. If you have settings needed for your watch app, you may use a settings bundle, just like on the familiar iPhone. That way it shows up on the native watch app for the container project.
The future is both exciting and unclear
Watchkit opens up a lot of fun avenues to take your old, traveled project on and give it new life. It’s up to time and consumers to show us whether or not this is the device of the future.
In any event, Apple’s mostly untarnished record of the 2000's will be largely contingent over the success of a stylized micro computer worn on one’s wrist. To become more educated over Apple Watch, be sure to visit Apple’s docs for more information.