# WatchKit

By [Mattt](https://nshipster.com/authors/mattt).
Published 2014-12-01.
Canonical URL: <https://nshipster.com/watchkit>

> This article covers the first version of WatchKit from 2014, when Apple Watch apps ran as extensions on the iPhone. watchOS 2 replaced that architecture, and storyboard-based WatchKit interfaces have been deprecated since watchOS 7. Build new watchOS apps with SwiftUI.

Everyone is excited about [ᴡᴀᴛᴄʜ](http://www.apple.com/watch/). Developers especially.

What’s the best way to get started? Look no further than [Apple’s WatchKit developer resources](https://developer.apple.com/watchkit/).

- Watch the “Getting Started” video—it’s like being in Moscone.
- Read the [Human Interface Guidelines](https://developer.apple.com/library/prerelease/ios/documentation/UserExperience/Conceptual/WatchHumanInterfaceGuidelines/index.html)—consider it a prerequisite for designing your application.
- Peruse the [WatchKit Programming Guide](https://developer.apple.com/library/prerelease/ios/documentation/General/Conceptual/WatchKitProgrammingGuide/index.html) and [WKInterfaceCatalog](https://developer.apple.com/library/prerelease/ios/samplecode/WKInterfaceCatalog/Introduction/Intro.html) for an introduction to everything the framework provides.
- And when you’re finally ready to add that App Extension target to your app, consult the [Lister Sample App](https://developer.apple.com/library/prerelease/ios/samplecode/Lister/Introduction/Intro.html) (in both Objective-C & Swift!) to see how everything fits together.

Apple’s Developer Publications, Developer Evangelism, and WatchKit teams knocked it out of the park with the WatchKit launch. The official resources are superb.

That said, after taking a look at everything, there were a few things that jumped out as it relates to UIKit. They’re the kind of subjective, opinionated things that don’t make for good documentation, but might be interesting or useful to anyone else as they’re getting started.

So this week, some initial impressions of WatchKit from the perspective of an iOS developer.

---

WatchKit harkens back to the earliest days of iOS development, when the platform limitations acted as liberating constraints for developers. Compared to OS X & AppKit, mired in decades of cruft and churn, iPhoneOS (as it was originally known) & UIKit were a breath of fresh air. Apps were small, simple, and humble.

After 7 years and as many major releases, iOS has grown to encompass myriad devices and configurations, from iPhones and iPads of all shapes and sizes, to the TV and CarPlay. It’s still an amazing developer experience (for the most part), but it feels like some of the magic has been lost along the way.

> **Counterpoint**: Nostalgia is bullshit. Remember, back in those days, there was no ARC, no GCD, no Interface Builder support for iOS and certainly no Swift. The indispensable open source libraries of the time were Three20 and asi-http-request. The state of the art for table view scroll performance was to manually composite text and images in a cell’s content view `drawRect:`. Life was solitary, poor, nasty, brutish, and short.

Regardless of where you’re personally coming from, the simplicity of WatchKit is something to be enjoyed and celebrated.

## Comparison to UIKit

WatchKit bears a striking resemblance to UIKit, which is not entirely surprising, given their shared history and purpose. Watches are different from phones and tablets, which themselves are different from desktops. Some concepts are shared, but each have unique purposes and constraints that shape the topography of their software.

For sake of comparison, here is how one might understand WatchKit in terms of UIKit / Cocoa concepts:

| WatchKit | UIKit |
| - | - |
| `WKInterfaceController` | `UIViewController` |
| `WKUserNotificationInterfaceController` | `UIApplicationDelegate` + `UIAlertController` |
| `WKInterfaceDevice` | `UIDevice` |
| `WKInterfaceObject` | `UIView` |
| `WKInterfaceButton` | `UIButton` |
| `WKInterfaceDate` | `UILabel` + `NSDateFormatter` |
| `WKInterfaceGroup` | `UIScrollView` |
| `WKInterfaceImage` | `UIImageView` |
| `WKInterfaceLabel` | `UILabel` |
| `WKInterfaceMap` | `MKMapView` |
| `WKInterfaceSeparator` | `UITableView.separatorColor` / `.separatorStyle` |
| `WKInterfaceSlider` | `UIStepper` + `UISlider` |
| `WKInterfaceSwitch` | `UISwitch` |
| `WKInterfaceTable` | `UITableView` |
| `WKInterfaceTimer` | `UILabel` + `NSDateFormatter` + `NSTimer` |

> As a [namespace prefix](https://nshipster.com/namespacing/), `WKInterface` sticks out like a sore thumb, but `WK` on its own was recently claimed by the new [WebKit](https://nshipster.com/wkwebkit/) framework. Although the Watch platform is a long way from being able to embed web views, the decision to demarcate things as they are is sensible.

There’s a lot of overlap, but there are important differences. Understanding those differences is both informative to making great WatchKit apps as well as enlightening in terms of how Apple’s thinking about API and best practices continues to evolve.

### WKInterfaceController

`WKInterfaceController` manages the elements in a scene, whereas `UIViewController` manages a view and its subviews. Interface objects are not views, but they act in similar ways.

The designated initializer for `WKInterfaceController` is `initWithContext:`, which accepts an optional `context` object:

```swift
override init(context: AnyObject?) {
    super.init(context: context)

    <#…#>
}
```

What’s a `context`? It’s anything you want it to be: a date, a string, a model object, or nothing at all.

The open-endedness of `context` may be disorienting at first, but it’s actually a remarkably clever solution to a long-standing problem of UIKit—namely, the difficulty passing information between view controllers. Without a standard convention for configuring `UIViewController`s as they are pushed, popped, and presented, developers are regularly faced with a miserable choice between custom designated initializers (incompatible with Storyboards), property configuration (prone to creating controllers with incomplete state), custom delegates (overly ceremonious when done correctly), or notifications (just… no). It’s for this reason that so many applications backed by Core Data fall into the pattern of referencing a shared `managedObjectContext` in the App Delegate.

But I digress.

Overall, `WKInterfaceController`’s API has a tiny footprint, and there’s no better illustration than its lifecycle methods:

```swift
// MARK: - WKInterfaceController

override func willActivate() {
    <#…#>
}

override func didDeactivate() {
    <#…#>
}
```

That’s it: 2 methods. No loading / unloading, no will / did appear / disappear, no `animated:YES`. Watch apps are simple by necessity. Communication between the iOS device driving the application and the watch is both time-consuming and battery-consuming, so all of the setup for the interface controller’s scene is to be done in the initializer and `willActivate`. Both during and after `didDeactivate`, the Watch will ignore attempts to update the state of interface elements.

Watch applications are either Hierarchical or Page-Based. This is similar to Xcode’s project templates for “Master-Detail Application”, “Page-Based Application”, and “Tabbed Application”, except that the design choices are mutually exclusive.

Hierarchical applications have an implicit navigational stack, which `WKInterfaceController` can manage with `-pushControllerWithName:context:` & `-popController`. One thing to note here is how `-pushControllerWithName:context:` takes a string—the name of the controller as specified in the Storyboard—rather than an instance of the controller itself.

Page-Based applications, on the other hand, act like a horizontal or vertical paged `UIScrollView`, with a pre-determined number of scenes each managed by a controller. It will be interesting to see which use cases are best served by Page-Based and Hierarchical interfaces. Without trying out stock applications on a real device, there’s not much context to understand the trade-offs of each intuitively.

As a final aside, there is an interesting pattern in Apple’s Swift sample code, to use inner structs as namespaces for Storyboard constants:

```swift
class WatchListsInterfaceController: WKInterfaceController, ListsControllerDelegate {
    struct WatchStoryboard {
        static let interfaceControllerName = "WatchListsInterfaceController"

        struct RowTypes {
            static let list = "WatchListsInterfaceControllerListRowType"
            static let noLists = "WatchListsInterfaceControllerNoListsRowType"
        }

        struct Segues {
            static let listSelection = "WatchListsInterfaceControllerListSelectionSegue"
        }
    }

    <#…#>
}
```

### WKInterfaceObject

`WKInterfaceObject` resembles a streamlined rendition of `UIView`, with properties for `alpha`, `hidden`, `horizontal` & `vertical` alignment, and `width` & `height`.

The most striking difference is the lack of a `frame`. Instead of manually specifying coordinate points or setting up Auto Layout constraints, WatchKit interface objects are laid out in a grid according to their margins and respective ordering, which is reminiscent of working with a CSS framework like [Bootstrap](http://getbootstrap.com/) (or for you Rubyists out there, remember [Shoes](http://shoesrb.com/)?).

Another departure from Cocoa Touch is that Target-Action methods use a fixed-format specific for each type of control, rather than passing a dynamic `sender` and `UIEvent`.

| Object | Action Method |
| - | - |
| Button | `- (IBAction)doButtonAction` |
| Switch | `- (IBAction)doSwitchAction:(BOOL)on` |
| Slider | `- (IBAction)doSliderAction:(float)value` |
| Table | `- (IBAction)doTableRowTapAction:(NSInteger)rowIndex` |
| Menu Item | `- (IBAction)doMenuItemAction` |

For the small, closed set of controls, this approach is really appealing—much better than typing `UIControlEventTouchUpInside`.

### WKInterfaceButton

`WKInterfaceButton` is an interface object that can be tapped to trigger an action. Its contents can be either a single text label or a group.

That latter part—being able to contain a group—is _huge_. This avoids one of the biggest gripes folks have with `UIButton`, the difficulty of adding subviews and having things position and interact correctly, which would otherwise drive people to give up and use `UITapGestureRecognizer`.

### WKInterfaceTable

Of all of the concepts carried over from iOS, tables are perhaps the most-changed.

`UITableView` is the backbone of iPhone applications. As such, they’ve evolved significant complexity to handle the demands of applications with a lot of data that needs to be displayed in many different ways. `WKInterfaceTable`, by comparison, seems marginal.

WatchKit tables do not have sections or headers, or footers, or editing, or searching, or data sources, or delegates. Rows are pre-populated at `WKInterfaceController -willActivate`, with each row specifying its own row controller (an `NSObject` subclass with `IBOutlet`s). `WKInterfaceController` can respond to table interactions either with the `table:didSelectRowAtIndex:` delegate method, or using the aforementioned Target-Action method.

It may not seem like much, but this approach is well-suited for the watch, and is a lot more straightforward than on iOS.

### WKInterfaceLabel

By contrast, `WKInterfaceLabel` is perhaps the least-changed thing carried over from iOS. With support for `NSAttributedString`, custom fonts, and font scaling, it’s pretty much everything you could ask for.

### WKInterfaceDate & WKInterfaceTimer

Let us not forget that time is a pretty important concept for a watch. As such, WatchKit introduces two new interface objects that are unprecedented in Cocoa or Cocoa Touch: `WKInterfaceDate` & `WKInterfaceTimer`.

`WKInterfaceDate` is a special kind of label that displays the current date or time. `WKInterfaceTimer` is similar, except that it displays a countdown until a specified `date`.

Including these two classes does as much to ensure app quality as anything else in WatchKit. Given how essential these tasks are for a watch, and how notoriously bad programmers are at using `NSDateFormatter` and `NSTimer`, one can only imagine where we’d be without these.

### WKInterfaceSlider & WKInterfaceSwitch

Sliders and Switches are due for a comeback on the watch. Without the benefit of touch gestures, interfaces are resigned to go back to basics. _Tap, Tap_, `On` / `Off`. _Tap, Tap_, `+` / `-`.

`WKInterfaceSlider` & `WKInterfaceSwitch` both appear to be well-crafted and rather customizable.

---

This is, of course, but a superficial reflection into the capabilities of WatchKit. Like I said at the beginning of the article, [Apple’s official resources for WatchKit](https://developer.apple.com/watchkit/) have everything you could ever need.
