WatchKit for watchOS 2: Initial Impressions

In this article I share my initial impressions of the updated WatchKit SDK for watchOS 2, including architecture, connectivity, and custom complications. By Mic Pringle.

Leave a rating/review
Save for later

Like Ray, I was unable to attend WWDC this year, but I’ve still been having an amazing time watching the videos, reading the docs, and discussing all the news with Jake, Nate, and the folks on the Tutorial Team.

As you may know from the podcast, I am a huge Apple Watch fan, so I was particularly excited about all of the goodies in watchOS 2.

I’ve been spending the last few days looking over the Apple Watch docs, so thought you might enjoy a quick overview of what’s new.

Please post any of your own thoughts in the comments below, and feel free to highlight anything I’ve missed!


Wait, did he just say native?

Wait, did he just say native?

Perhaps one of the biggest changes to WatchKit with this release is that you can now build native watch apps.

Unlike the previous version of watch apps where the interface ran on your watch but the code was executed on your iPhone, with watchOS 2 both reside and execute on the watch itself.

This has some very positive side-effects, such as making your apps launch quicker, and be far more responsive since there’s no longer a round-trip to your phone over Bluetooth LE with every interaction.

This move to native apps does also have some implications that you need to be aware of:

  • openParentApplication(_:reply:) has been removed from the SDK. But don’t panic, as it’s been replaced by the much richer Watch Connectivity framework. More on this shortly.
  • Sharing files using shared app groups is no longer an option. Again, you can use the new Watch Connectivity framework to facilitate this, but Apple has also provided network access for native apps in watchOS 2. So, if you were using app groups to share data pulled down from the internet, you can now do this directly on the watch using good ol’ NSURLSession.
  • iCloud isn’t available on the Watch.

Watch Connectivity

With the Watch Connectivity framework you can pass files and data back and forth between the watch and its paired iPhone. If both apps are running in the foreground, then the communication is live, otherwise it happens in the background so that the data or file is available when the receiving app is launched.

The main player in this new framework is WCSession, which handles all the communication between the two devices. You don’t create instances of this class yourself, but instead use the defaultSession singleton object.

To get up and running you simply assign an object that conforms to the WCSessionDelegate protocol to the session’s delegate property, and call activateSession(). If you plan on making frequent use of Watch Connectivity then I highly recommend you do this setup as early in your apps lifecycle as you can.

Once you have your session configured and activated, you can use any of the following methods to transfer your data and files:

  • updateApplicationContext(_:error) is used to transfer a dictionary of data to the counterpart app. This won’t always happen immediately, but will happen before the counterpart app wakes up so that the data is available at launch. The counterpart receives the dictionary via it’s session delegate’s session(_:didReceiveUpdate:) method.
  • sendMessageData(_:replyHandler:errorHandler:) is used to transfer data to the counterpart app immediately. Calls to this method are queued up and delivered in the same order in which you send them. If you’re sending data from the watch to the iOS app, then the app is woken up in the background if it’s not already running. If you’re sending data in the other direction and the watch app isn’t running then the error handler is called. The counterpart receives the data via it’s session delegate’s session(_:didReceiveMessageData:replyHandler:) method.
  • transferFile(_:metadata:) is used to transfer files, such as images, in the background. This behaves in the same way as the previous method, waking the iOS app up if it’s not running, or calling the error handler if the watch app isn’t running. The corresponding delegate method you need to implement to receive the file is session(_:didReceiveFile:).

There are numerous other methods provided by the framework, so I highly recommend you check out the reference.

See, didn’t I tell you not to worry about losing openParentApplication(_:reply:). :]

Other WatchKit Highlights

I’ve gone into detail on two of the biggest changes in this release of WatchKit, but there were several other highlights that I think are worthy of a mention.


While WatchKit still includes its original approach to animation, cycling through a pre-generated series of images, WKInterfaceController now provides support for basic animations that are more akin to iOS, via the new animateWithDuration(_:animations:). This takes a duration and a block, and animates any changes made to interface objects within that block over the provided duration. For example:

animateWithDuration(1) { () -> Void in 

You can animate changes to the following properties of WKInterfaceObject:

  • alpha
  • width and height
  • vertical and horizontal alignment
  • background color
  • layout group insets
Note: Animations aren’t supported in glances or custom notifications, and any changes you make in the animation block will be applied immediately without animations.

I realise this may seem a little rudimentary since there’s no way to provide a timing curve, or know when the animation is complete, but I’m sure you’ll agree that it’s definitely a step in the right direction, and I’m hoping Apple will build on this in future seeds.

More Access To The Hardware

WatchKit for watchOS 2 provides access to much of the devices hardware and sensors, including the Digital Crown, Taptic Engine, heart rate sensor, accelerometer, and microphone.

This opens up a whole new world of functionality for your apps, such as being able to accurately monitor the heart rate of a user of your fitness app as they work out, or use the Taptic Engine to provide a more immersive gameplay experience. I honestly can’t wait to see what you all come up with! :]

New Interface Objects

With this release of WatchKit Apple has shipped a brand new interface object: WKInterfacePicker. This presents a scrollable list of items, which you interact with via the Digital Crown.

The items in the picker can be text, images, or a mix of the two. When the user selects an item, WatchKit calls the picker’s action method passing the index of that item.

A picker can be displayed using one of three different styles:

  • List: this displays the items as a vertically stacked list;
  • Stacked: this displays the items like a stack of cards that animate in from the bottom of the picker as the Digital Crown is turned;
  • Image Sequence: this displays a single image from a sequence of images.

It’s also worth pointing out that a single interface controller can include multiple pickers.

And speaking of interface controllers, WKInterfaceController now exposes a method that allows you to present alerts and action sheets.

Calling presentAlertControllerWithTitle(_:message:preferredStyle:actions:) presents an alert or action sheet over the current interface controller, depending on the style you pass as the preferredStyle parameter. The actions parameter is probably the most interesting of the four, as this takes an array of instances of WKAlertAction, which themselves provide a block to execute when the corresponding button is tapped by the user. It’s also worth noting that you’re responsible for dismissing the alert or action sheet within these blocks.

Mic Pringle


Mic Pringle


Over 300 content creators. Join our team.