WatchKit Example Hero

Hello WatchKit! Learn how to build an Apple Watch app

WatchKit is here and that means it’s time to learn how an Apple Watch app comes together. This example should provide plenty of insight into how the device works so that you can begin to think about how your apps could leverage this incredible accessory.

Without a doubt the watch will be an amazing supplement to the things our customers want to achieve during their day. If we can slice off a minute, while not completely derailing them, it’ll be a big convenience win.

In order to experiment with this example you’ll need to be a registered developer with access to Xcode 6.2.

In the event that you’re completely new to iOS it’s important to note that this example is not beginner friendly. We have a lot of areas that are covered (frameworks, extensions, notifications, storyboards, …) which would be better served as a guide. That said, if you’re feeling froggy, feel free to grab the example project near the bottom of this article and play around.

Quick Thoughts

One of the more surprising bombs to drop was just how much the Apple Watch needs the iPhone. As it stands, version 1 of the Apple Watch is essentially a viewport into the core app state on iPhone. If you were hoping to write a native experience you’ll have to wait. This will change, but you’ll have to wait until next year.

That’s not necessarily a bad thing in my mind, but I do wonder what the average consumer will think. Apple needs to maintain quality (which has been suffering lately) and style. Cramming a massive feature list into this thing for v1 is not a wise move and you should avoid doing that with your products, too.

I hope you like storyboards! Right now user interface elements cannot be added or removed from the view hierarchy programmatically. You’ll need to lay out your interface and manage layout by showing & hiding elements. Elements are also managed by relative positioning so you can’t explicitly set origin information. My initial impressions are mostly positive. I’m really interested to see how designers leverage the capabilities here.

Architecture is important. In order to avoid duplicating code you’ll want to learn how to create and manage a framework that can be shared between your extension and your app. While you may not sense the need right away, if you start seeing a lot of duplicated effort you should consider moving it into a framework.

Important Resources

WatchKit Programming Guide (easy read)
Apple Watch Human Interface Guidelines (easy read)
Understanding How an App Extension Works
Registering, Scheduling, and Handling User Notifications

Time For An Example

Today I’ll do a quick walkthrough of an Apple Watch app. Here we’re building an application that will allow us to set price alerts for equities we wish to track. When the price of an equity drops below our target price, the condition is met and we’ll be alerted. This is a great use case for an Apple Watch. The user doesn’t need to pull out their phone to access this alert. We can deliver that information via the watch so they can begin making an assessment on leaving the position or adding to it as soon as possible.

Don’t forget. The watch is essentially a viewport into the iPhone app you’ve already written. Your iPhone app is collecting, processing, and managing data. The watch app lets you quickly monitor whichever state you choose to reveal and should not be doing any heavy lifting due to speed. You can’t have an Apple Watch app without an iPhone app.

The structure of our watch app is fairly straightforward. The app provides a glance, notification, and main user interface. I’ll explain each of those in more detail below.

WatchKit Example Overview

Framework

I’ve included a very simple framework to illustrate how data could be shared between our watch app and the glance. This example doesn’t include a dynamic notification, but we could leverage the framework there if we did.

Nothing fancy is going on within our framework. It just tracks our equities so we can retrieve them as needed.

As a friendly reminder: the key here is speed. We don’t want to wait to retrieve and/or process data in order to update our interface. That information should be within the app already. We build our interfaces within storyboards and quickly manage things by showing & hiding elements so we don’t force the user to wait. If it takes you 10 seconds to pull out your phone and open an app, it’ll take a fraction of that to look at the watch. This watch shouldn’t be doing any heavy lifting. It should just echo information from your iPhone app.

Future version of the Apple Watch will manage all of this quicker when they introduce the ability to write native apps for the watch.

Interface

WatchKit Example Overview

Here our main interface reveals up to 4 stocks we’re currently tracking. We can swipe left to navigate through a few pages. If we press the ‘Targets Hit’ action we’ll be shown which targets have satisfied our goal of falling below our target price.

With all interface files you’ll usually do one, or more, of the following:

  • Fetch data from your modal to display
  • Configure labels, images, and other controls
  • Show / hide interface objects depending on the need

You have much more freedom with your main interface. You can scroll the content up or down and provide pages of content that the user can swipe over to. When you need the user to perform a specific action you can present a modal controller to focus their experience.

Keep the background of your watch app black since the edges of the actual device will be black. Additionally, the device will naturally provide padding, due to the it’s edges, so you don’t have to worry about insets for your elements—design to the edges.

It’s important to remember that you can’t explicitly lay your controls out by defining an origin. Xcode does this for you by stacking everything beginning at the top-left of the screen. You can lay your content out vertically or horizontally by using groups, which you’ll undoubtedly do. In this example scan the Targets Hit scene to see this in practice. Everything starts out vertical, but then I add a couple of groups to lay content horizontally.

When you’d like to navigate you have 2 options.

  • You can push controllers onto a navigation stack by calling pushControllerWithName:context: and pop an interface by calling popController.
  • You can create a page-based interface, which turns your interface into a paged scrollview. This is how the current example works.

One last thing to note. If you need to provide any kind of animation be prepared to cut out a lot of png files. As it stands you’ll need to create frame-based animations due to performance concerns. You can cache these images (up to about 20MB) so they’re easily retrieved by the device.

In the provided example you can swipe left to move into different pages. On the main page I have an action that presents the targets hit controller modally.

Read more about interfaces
Apple Watch Human Interface Guidelines: Interface
WatchKit Programming Guide: Interface

Glance

WatchKit Example Overview

A glance view is useful in the event we’d like to provide the user with important information. Think of an airline glance revealing flight information. In our app here we’re showing the user their latest price targets that have been hit. Our app isn’t fully-loaded at the time a glance is revealed, but can still showcase important information we may have received. If the user wants additional information they can tap on the view and they’ll be moved into the app.

What if the glance involves a different area within the app other than you main user interface? In that case we can register that information and pass it to our app when they touch the view. You can see this in action inside GlanceController.swift.

self.updateUserActivity("glance", userInfo: ["identifier": "targetsHit"])

This identifier must match the identifier you’ve provided in your storyboard.

When the user touches the view, our main interface controller will be notified with the information we applied. We then read the identifier and return that so the watch app knows which controller to load. You’ll see that in action inside InterfaceController.swift.

override func actionForUserActivity(userActivity: [NSObject : AnyObject]?, context: AutoreleasingUnsafeMutablePointer<AnyObject?>) -> String? {
    var val = ""
    if let dict: Dictionary<String, String> = userActivity as? Dictionary<String, String> {
        val = dict["identifier"];
    }
    return val
}

That’t the only thing about glances that tripped me up. Everything else is laying out and populating the interface, which is fairly straightforward. Glances do not provide scrollable content so you don’t have a lot of room to work with.

Read more about glances
Apple Watch Human Interface Guidelines: Glance
WatchKit Programming Guide: Glance

Notification

WatchKit Example Overview

Notifications come in two flavors.

Short look notifications alert the user that an app has received a notification. These are extremely basic. They’ll reveal the app icon, the app name, and the title string from your notification. The biggest concern here is the title. It pays to keep the title string extremely focused. In this example app I reveal ‘Target hit.’

Long look notifications appear when the user keeps their arm up for a period of time. The layout here can be static or dynamic based on what you need. In this example I’ve just stayed with a static notification that reveals information provided in our notification payload file. Review the programming guide to see how to properly register interface updates. Hint: You’ll respond to the notification within your notification controller via the didReceive methods.

When you provide custom action buttons within a notification you’ll need to process those actions depending on if your watch app is in the background or foreground. If the app is in the foreground you’ll implement one of the two methods in your main interface controller:

override func handleActionWithIdentifier(identifier: String?, forLocalNotification localNotification: UILocalNotification) {
    NSLog("Handle Action For Local Notification")
}
    
override func handleActionWithIdentifier(identifier: String?, forRemoteNotification remoteNotification: [NSObject : AnyObject]) {
    NSLog("Handle Action For Remote Notification")
}

Background actions will launch your iOS app in the background so that it can process the action. The notification information will pass through your app delegate.

Your payload should include a category identifier so you know which controller to load. In the provided example I’ve set that to ‘PriceHit’ within the PushNotificationPayload.json data file.

If you have any trouble getting the notification to appear when you first attempt running it simply stop and run the app again.

Read more about glances
Apple Watch Human Interface Guidelines: Notifications
WatchKit Programming Guide: Notifications

Testing

In order to properly test all of these elements of your app you’ll need to set up a couple of schemes.

You’ll need to duplicate your watch scheme twice and set the appropriate executable target. From there you’ll be able to run your app triggering a glance or a notification. In order to properly test notifications you’ll need to provide a PushNotificationPayload.json file, which is automatically included if you choose to add a notification scene to your app during project creation.

I’ve created a short animation showing off this process.

[annotated header=”Duplicating Schemes” annotation=”Click the GIF to increase the size”]
WatchKit Scheme Guide
[/annotated]

Challenge

Consider grabbing the example and updating the static notification to a dynamic notification.

Go grab the project! Rip it to shreds exploring it and add something to it. Have fun!

[alert color=”yellow”]github.com project[/alert]

Question & Answer

[alert color=”blue”]When I duplicate my scheme I don’t see a glance or notification executable to select. What’s wrong?[/alert]
You’ll need to make sure sure that you have a simulator selected instead of your device. When you’re editing a scheme you can change that by clicking the scheme title on the top-left of the window.

[alert color=”blue”]What are the known issues that I should be aware of?[/alert]
If you run your project and don’t see a separate simulator screen appear for your watch app, select your iOS simulator and choose the watch option from Hardware > External Displays.

Find more known issues by reading the Xcode 6.2 Beta Release Notes.

Takeaway

Probably the most important elements of all of this are glances and notifications. Of course the main interface will be important, but I just visualize the other areas really owning the experiences most people take advantage of on the device.

As always, if you enjoyed this content I’d deeply appreciate sharing it with a developer friend or two.

Sign up to my newsletter on the right side of the site to stay connected. I plan to send short and sweat heartbeats once a month, plus exclusive thoughts/discoveries that you may find valuable.

Thanks for reading. Best wishes for a productive day!


Posted

in

by

Comments

2 responses to “Hello WatchKit! Learn how to build an Apple Watch app”

  1. NilStack Avatar
    NilStack

    Great! Thanks for sharing this.

    1. David McGraw Avatar

      Very welcome! Thanks for stopping by.

Leave a Reply

Your email address will not be published. Required fields are marked *