Home Archive Tutorials

WatchKit FAQ

Check out the answers to the most commonly asked questions about WatchKit – Apple’s framework for making Apple Watch apps!

Note from Ray: This is an article on WatchKit released as part of the Spring Swift Fling celebration. We hope you enjoy! :]

WatchKit has been available to developers for about three months (at the time of writing this post). As developers get to know this cool new technology, a lot of questions undoubtedly come up.

In this WatchKit FAQ, we’ll answer a bunch of frequently asked questions that we’ve seen around forums, Twitter, email and Stack Overflow. We’ll also periodically update this FAQ as new questions bubble up.

For some questions there aren’t clear solutions, so some answers are a mix of wisdom, opinion and an occasional educated guess. Just like you, we’re learning more about WatchKit as we go along, and the tech is still under heavy development and therefore subject to change.

Make sure to share your opinions and comment about what you like and don’t like in WatchKit, and ask more questions; we’ll update this FAQ based on your feedback.

Basic Questions

What is WatchKit and how does it work?

WatchKit is Apple’s framework for building hybrid apps for the Apple Watch, and it is bundled with Xcode 6.2.

WatchKit works by splitting your app into two distinct parts:


  • Your Apple Watch contains just the user interface resources like the storyboard and asset catalog, and even though it handles user input it doesn’t actually execute any of the code. In other words, the Apple Watch behaves just like a thin client.
  • Your iPhone contains all the code, and executes it as an extension, just like a Today or Action extension.

One cool thing is that communication between the Apple Watch and the iPhone is automatic and happens behind the scenes.

You work the way you’re used to and WatchKit handles all the wireless communication on your behalf. As far as the code you write is concerned, your views and outlets are connected locally even though they’re on a completely separate device. Pretty cool stuff!

To learn more, check out our WatchKit: Initial Impressions post.

What’s the difference between Xcode 6.2 beta and Xcode 6.3 beta? Which one should I use for WatchKit development?

If you’re planning to submit your WatchKit app the moment the App Store starts accepting them, you should use the latest Xcode 6.2 beta.

Xcode 6.3 comes with the new version of Swift – 1.2 – and according to threads in the Apple Developer Forum, Xcode 6.3 won’t be out of beta when Apple Watch is released, so you won’t be able to submit apps built with this version in time for the Apple Watch launch.

You can learn more about Xcode 6.3 and Swift 1.2 in our What’s New in Swift 1.2 post.

Can you build Apple Watch apps in Swift?

Yes, you can build apps for the Apple Watch in either Objective-C or Swift, or a combination of both. Apple has provided two sample projects for WatchKit:

In addition, our WatchKit Tutorial, WatchKit video tutorial series, and WatchKit by Tutorials book are all written exclusively in Swift.

Apple has also provided the WatchKit Framework documentation in both Objective-C and Swift.

Can I create custom watch faces?

No. Custom watch faces are not currently supported.

Watch Faces!

Watch faces are not supported yet!

How many Apple Watches can I pair with one iPhone?

You can pair one Apple Watch with one iPhone at a time — it’s an exclusive relationship.

Can I pair my Apple Watch with an iPad?

No. The Apple Watch only pairs with an iPhone at this time.

Can an iPhone app wake up its WatchKit extension and watch app?

No. The WatchKit extension can only ask the system to launch the companion iPhone app, which it will do so in the background. There is currently no support for this to work the other way around.

Can third-party apps make phone calls from a watch app?

No. There is no public API that lets you initiate a phone call directly from a WatchKit extension. Since the companion iPhone app can’t be brought to the foreground either, the system silently ignores all phone call or openURL: requests from the companion iPhone app.

Can you access the heartbeat sensor and other sensors on the watch from your watch app?

No. There is currently no API to access the hardware sensors on the Apple Watch at this time.

What are the differences between short-look, long-look, static and dynamic notifications?

  • Short-Look: A Short-Look notification is provided by the system. Similar to a notification banner you receive on an iPhone, you don’t have any control over a Short-Look notification. A Short-Look notification displays your app icon, app name and the title string from the notifications payload. When a notification arrives, a user sees the Short-Look notification. If the user raises their wrist, after a slight pause, the Short-Look notification will transition to the Long-Look notification.
  • Long-Look: A Long-Look notification can be either Static or Dynamic.
    • Static: A static notification includes a single label that is populated automatically using the notifications payload. You can create a static notification scene in your watch app’s storyboard, but can’t really customize it beyond changing the color of the sash and the title.
    • Dynamic: A dynamic notification requires you to subclass WKUserNotificationInterfaceController. It’s instantiated from your storyboard, and you can provide your own custom interface. Note that there are no guarantees a dynamic notification interface will be displayed. For example, if the watch’s batteries are low, the system may decide to show the static notification interface instead to preserve battery as they are less expensive to create.

Under The Hood

Select the appropriate scheme

Select the appropriate scheme

How can I test a glance or a notification using the simulator?

Each glance or notification requires its own dedicated build scheme to run in the simulator. Then you simply select the appropriate scheme, and build and run.

Can I position interface elements on top of each other?

No, interface elements can’t be positioned on top of each other natively. However, there are workarounds. For example, you can use a WKInterfaceGroup and set its background image to something that represents the control you want to overlay. Inside the group you can then add the necessary labels, buttons and so on.

Can I customize the CALayer property of interface elements?

No. There is no CALayer property available on the Apple Watch interface elements, as they don’t descend from either UIView or CALayer.

Can I subclass the classes available in WatchKit?

There is nothing to stop you from subclassing a class in WatchKit, but you might find you’re unable to use it. You can subclass some classes, such as WKInterfaceController and WKUserNotificationInterfaceController and use those in your storyboard.

However, the storyboard of a watch app doesn’t allow you to change the class of any interface elements. And you’ve can’t dynamically create interface elements and insert or remove them as subviews; you can only hide or show interface elements that are already present in the storyboard.

Can I mix page-based and navigation-based interface controllers?

Yes, but with some limitations.
If you have a hierarchical interface, you can present a page-based interface modally. If any of the pages is a hierarchical interface, the root of that interface is displayed and you won’t be able to push anything on its stack.
If you have a page-based interface, you can present a hierarchical interface modally, but only the root interface controller is displayed and you won’t be able to push anything on its stack.

Are there equivalents for UIActivityIndicator or UIAlertController on the Apple Watch?

No, but in lieu of a UIAlertController, you can display a custom WKInterfaceController modally.
You can work around an activity indicator by adding a sequence of images to create the necessary animation, or simply display a label with the appropriate text. For an example of this, check out Apple’s Lister example. In the Watch App’s glance, you’ll see there are 360 images representing a single circular animation!


Can I use Core Graphics to generate images dynamically and then use them in a watch app? Can they be cached on the watch?

Yes, but the composition of any images using Core Graphics must take place on the iPhone as part of the extension. Once you have rendered the Core Graphics drawing context into an instance of UIImage you can then cache it on the watch using addCachedImage(_:name:) from WKInterfaceDevice.

Can I use custom views in the Apple Watch? Can I customize the interface elements beyond their public API?

No. You can’t use custom views. WatchKit only supports certain native interface elements. None of the interface elements can be subclassed or customized beyond their public API. The available interface elements are WKInterfaceLabel, WKInterfaceButton, WKInterfaceImage, WKInterfaceGroup, WKInterfaceSeparator, WKInterfaceTable, WKInterfaceSwitch, WKInterfaceMap, WKInterfaceSlider and WKInterfaceTimer.

How does the Apple Watch communicate with your iPhone?

The Apple Watch leverages both Bluetooth LE and Wi-Fi technologies to communicate with its paired iPhone. The exact nature of the communication and its implementation is opaque to both users and developers.

Turn on Wi-Fi  and Bluetooth after turning on Airplane mode

Turn on Wi-Fi and Bluetooth after turning on Airplane mode

Can I use the Apple Watch while in Airplane Mode?

Yes. In fact, you can turn Bluetooth and Wi-Fi on after enabling Airplane mode to enable communications and continue using your watch.

What happens to my app when the Apple Watch can’t communicate with its paired iPhone?

Simply put, your app won’t run, and if it’s already running it’ll be suspended.

In the WatchKit extension, didDeactivate() will be called on the current interface controller and you’ll be given the chance to do any necessary cleanup. A red iPhone icon will display in the status bar on the watch to indicate loss of connectivity, and the interface will remain on screen, but won’t be interactive. Users can either restore connectivity or exit the app.

How can a watch app communicate with its companion iPhone app?

There are various techniques you may use, a popular being that the watch app writes or updates data in a shared container, and then it notifies the iPhone app. Afterwards, the iPhone app can pull in the changes from the shared container.

Another technique is to pass data to the iPhone app via a dictionary, but this can only be initiated by the watch app. There is a single API for this in the WatchKit extension; call the class method openParentApplication(userInfo:reply:) of WKInterfaceController, as shown in the following code snippet:

// Notify companion iPhone app of some changes in the shared container.
let kSharedContainerDidUpdate = "com.rayWenderlich.shared-container.didUpdate"
let requestInfo: [NSObject: AnyObject] = [kSharedContainerDidUpdate: true]
WKInterfaceController.openParentApplication(requestInfo) { (replyInfo: [NSObject : AnyObject]!, error: NSError!) -> Void in
  // Handle the reply from the companion iPhone app...

In the userInfo dictionary, you simply pass a flag or some data for the companion iPhone app to act upon. To receive this communication, the companion iPhone app must implement application(_:handleWatchKitExtensionRequest:reply:) in its app delegate:

func application(application: UIApplication!, handleWatchKitExtensionRequest userInfo: [NSObject : AnyObject]!, reply: (([NSObject : AnyObject]!) -> Void)!) {
let kSharedContainerDidUpdate = "com.rayWenderlich.shared-container.didUpdate"
  if let isUpdate = userInfo[kSharedContainerDidUpdate] as? Bool {
    // Process request, then call reply block

If the companion iPhone app is suspended or terminated, the system will launch it in the background. Depending on the purpose of the communication, the companion iPhone app may return something in the reply block which the watch app can then process accordingly.

How can an iPhone app communicate with its watch app?

There is no way for an iPhone app to initiate communication with its extension. Aside from writing to a shared container, or responding to the watch app’s requests, the iPhone app may use the Darwin Notification Center to notify the WatchKit extension about a particular event — Darwin Notification Center is an API of the Core Foundation framework.

If you decide to use the Darwin Notification Center, there are some very important things to remember:

  • An application has only one Darwin Notification Center.
  • All Darwin notifications are system-wide.
  • The main thread’s run loop must be running in one of the common modes, such as kCFRunLoopDefaultMode, for notifications to be delivered.
  • The watch app must be running in the foreground to handle sending and receiving Darwin notifications.
  • You can’t pass objects via Darwin notifications because they only carry a name and a userInfo dictionary.
  • Darwin notifications are not persisted, rather, they are delivered immediately. Therefore, if an observer is suspended, terminated or placed in the background, the notification is lost.

What happens if I don’t implement static or dynamic notification interfaces?

Even if you don’t have a watch app, the system will still display notifications for your iPhone app on the watch. However, the default notification interface has no custom styling. If you have interactive notifications, the system will hide those actions on the watch.

What’s the difference between setImage(_:) and setImageNamed(_:)?

You should use setImageNamed(_:) when the image you want to display is either cached on the watch on is in an asset catalog in the watch app’s bundle, and use setImage(_:) when the image isn’t cached — this will transfer the image data to the Apple Watch over the air!

An image is cached on the watch if it’s one of the following:

  1. Bundled with the watch app target in the project, meaning that the image resides in the asset catalog belonging to Watch App target in the project
  2. Explicitly cached on the watch beforehand via one of these WKInterfaceDevice APIs: addCachedImage(_:name:) or addCachedImageWithData(_:name:)

Can I use iCloud in a watch App?

Yes, you can use iCloud with the Apple Watch app. Lister: A Productivity App, which is one of the sample projects provided by Apple, demonstrates how to use iCloud in this context.


How can I add animations to my watch app?

There is only one way to display animations on the Apple Watch: image sequences. To make something appear animated, you have to pre-generate a series of images, and then cycle through them like a flip-book. The era of the animated GIF is back! ;]


You can display a sequence of static images in a WKInterfaceImage object to create your own custom animations.

@IBOutlet weak var image: WKInterfaceImage?
image?.setImageNamed(image1) // Load the initial image using the required <name><number> format
image?.startAnimating() // Starts animating
image?.stopAnimating() // Optional. Stops animating.

You can also animate only a subset of images as shown in the following code snippet:

image?.startAnimatingWithImagesInRange(range, duration: 2, repeatCount: 1)

Can I create animations for the Apple Watch in code?

Yes, but perhaps not in the way you think – as I mentioned above there is no Core Animation framework or equivalent. You can use Core Graphics to render each frame of the animation to an offscreen context, render it to an instance of UIImage, and at the end you’ll have a sequence of images you can animate on the Apple Watch.

The following code snippet shows how you can create an animation for a moving circle using Core Graphics by generating an image sequence for each frame (code courtesy of Jack Wu from WatchKit by Tutorials):

// Create an offscreen context
UIGraphicsBeginImageContextWithOptions(size, opaque, scale)
let context = UIGraphicsGetCurrentContext()

for centerX in 0..100 {
  // Draw a circle at centerX.
  // Create a snapshot.
  let image = UIGraphicsGetImageFromCurrentImageContext()

  // Write the image as a file
  let data = UIImagePNGRepresentation(image)
  let file = "path\\image_\(centerX).png"
  data.writeToFile(file, atomically: true)

// End the context.


What is the maximum animation frame rate on the Apple Watch?

You can’t set the animation frame rate on the Apple Watch. However, it’s possible to set the animation length and the let the system automatically determine the frame rate.

If the sequence of images are sent over the air, for instance when images are not cached, they will run up to 10 fps. If the images are already cached on the Apple Watch via the image cache or asset catalog in the WatchKit app bundle, they will run up to 30 fps.

Debugging and Unit Testing

How can I run and debug both the iPhone app and the Apple Watch app at the same time using the simulators?

  1. Build and run the watch app; this launches the Apple Watch simulator, runs the watch app and attaches it to the debugger.
  2. Then in the iOS simulator, tap on your iPhone app’s icon to launch it.
  3. Now go back to Xcode, and from the top menu select Debug\Attach To Process and then select the appropriate iPhone app. This will add a new process to your Xcode Debug Navigator and attach the iPhone app to the Debugger.

How can I unit test my WatchKit extension?

You can write unit tests for your watch app in the same way you write unit tests for your iPhone or iPad apps; simply add a new Unit Test target for the WatchKit extension to your project. However, you can’t specify the watch app as a Host Application.


For the iPhone app target, the iPhone application appears as the Host Application


But for the WatchKit Extension target there is no Host Application

You have to add every single file that you want to test to the WatchKit extension Unit Test target explicitly.


Add the files that you want to test from the WatchKit extension to the Unit Test target

Sharing Data

How can you share data between a WatchKit extension and its containing iOS app?

You need to enable App Groups; this refers to a container on the local file system that both an extension and its containing iPhone app can access. You can define multiple app groups and enable them for different extensions.

Once App Groups are enabled, you can use either of the following techniques, based on your needs:

  • Read and write to a shared container directly. You get the URL of the shared container by asking NSFileManager. There is a single API for this:
    let kMyAppGroupName = "com.raywenderlich.mywatchapp.container"
    var sharedContainerURL: NSURL? = NSFileManager.defaultManager().
  • Use shared NSUserDefaults. To create defaults storage in the shared container, you need to initialize a new NSUserDefaults instance using NSUserDefaults(suiteName:) and pass in the unique identifier of the app group, like so:
    let kMyAppGroupName = "com.raywenderlich.mywatchapp.container"
    let sharedUserDefaults = NSUserDefaults(suiteName: kMyAppGroupName)

Note: When you want to read from or write to a shared container, you must do so in a coordinated manner to avoid data corruption, because a shared container can be accessed simultaneously by separate processes. The recommended way to coordinate reads and writes is using NSFilePresenter and NSFileCoordinator. However, it’s advised against using file coordination APIs in an app extension because they can result in deadlocks.

The reason behind this is the lifecycle of app extensions. App extensions have only 3 states: (a) running, (b) suspended and (c) terminated. If an app extension that uses file coordination APIs is suspended while writing, it never gets the chance to relinquish ownership, so other processes get deadlocked.

However, an iPhone or an iPad application is notified via its app delegate when it’s placed in the background, and it should then remove file presenters. When the app is brought back to the foreground, the file presenters can be re-added.

Instead, you can use atomic safe-save operations like NSData‘s writeToURL(_:atomically:). SQLite and Core Data also allow you to share data in a shared container in safe manner between multiple processes, even if one is suspended mid-transaction.

You can learn more about this in Technical Note TN2408: Accessing Shared Data from an App Extension and its Containing App.

How can you share a Core Data database between a watch app and an iPhone app?

To share a Core Data persistent store file, you essentially use the same mechanism as shown for the shared data example. Below is a code snippet to show how this works:

let kMyAppGroupName = "com.raywenderlich.mywatchapp.container"
var sharedContainerURL: NSURL? = NSFileManager.defaultManager().
if let sharedContainerURL = sharedContainerURL {
  let storeURL = sharedContainerURL.URLByAppendingPathComponent("MyCoreData.sqlite")
  var coordinator: NSPersistentStoreCoordinator? = 
    NSPersistentStoreCoordinator(managedObjectModel: self.managedObjectModel)
    configuration: nil,
    URL: storeURL,
    options: nil,
    error: nil)

Let’s Get Down to Business

Can you make games for the Apple Watch? What kinds of games are suitable?

While it’s still too early to say what type of games will succeed and whether users will want to play games on the watch, it almost goes without saying that you’ll need to think about the Apple Watch from a different perspective.

Remember how games for iPhone and iPad required a different mentality when compared to desktop games? Likewise, the Apple Watch will require a unique approach.

We know already there are limits to what you can do because there is no API for hardware access on the Apple Watch, nor does it support gesture recognizers or allow custom drawing on the screen. Remember, you can only use native interface elements.

But don’t let those limits put a dampener on your creativity; think of them as ground rules. :]


How can you earn money with Apple Watch apps?

It’s still far too early to say. One thing to note: iAd is not supported, and considering the small screen size and the amount of time a user will interact with your watch app, on-screen advertisements would probably annoy users and not perform well enough to be financially worth it anyway.

Also, if the WatchKit extension is included in your app bundle, you can’t disable it or otherwise prevent user from installing it. So, it can’t be supplementary that you make available through in-app purchases.

However, there are still ways that you can monetize a WatchKit extension:

  • If you have a free version app and a paid version app in the App Store, you could just implement the WatchKit extension in the paid app version.
  • If you have an app with in-app purchases, you could just display limited information in the extension, but allow a user to unlock additional features via in-app purchases.

This is obviously not an exhaustive list of the possibilities to monetize WatchKit apps, but one thing is clear: you’re going to have to been just as creative with your monetization as you are with the watch apps themselves.

Is there any reason to believe watch apps are a new opportunity that might let developers make a living just by developing for the App Store?

Any judgements at this point are premature. Even though the Apple Watch is indeed a brand new platform full of new opportunities, it may not create a similar gold-rush era to the one we saw when the App Store first launched.

One thing to keep in mind is that the Apple Watch is a different proposition entirely. Given its aesthetics and price tag, it’s more akin to jewelry that communicates with your iPhone than an essential device.

However, a WatchKit extension could make it easier for an app to stand out in the crowd. Much like the days when native iPad apps were more successful than iPhone apps that were merely scaled to fit, a thoughtful, well-designed Apple Watch app that complements an iPhone app could drive sales.

More Questions?

If you have any questions that weren’t covered here (And I know you do!) please post a comment. We’ll pick out the most frequently asked, compelling and even challenging to update the post – and you’ll also get attribution just for asking!

Also, as mentioned earlier, please chime in with any comments or clarifications for the answers listed here and we’ll update as needed.

Thanks all!


More like this