WatchKit FAQ
Check out the answers to the most commonly asked questions about WatchKit – Apple’s framework for making Apple Watch apps! By Soheil Azarpour.
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Sign up/Sign in
With a free Kodeco account you can download source code, track your progress, bookmark, personalise your learner profile and more!
Create accountAlready a member of Kodeco? Sign in
Contents
WatchKit FAQ
30 mins
- Basic Questions
- What is WatchKit and how does it work?
- What’s the difference between Xcode 6.2 beta and Xcode 6.3 beta? Which one should I use for WatchKit development?
- Can you build Apple Watch apps in Swift?
- Can I create custom watch faces?
- How many Apple Watches can I pair with one iPhone?
- Can I pair my Apple Watch with an iPad?
- Can an iPhone app wake up its WatchKit extension and watch app?
- Can third-party apps make phone calls from a watch app?
- Can you access the heartbeat sensor and other sensors on the watch from your watch app?
- What are the differences between short-look, long-look, static and dynamic notifications?
- Under The Hood
- How can I test a glance or a notification using the simulator?
- Can I position interface elements on top of each other?
- Can I customize the CALayer property of interface elements?
- Can I subclass the classes available in WatchKit?
- Can I mix page-based and navigation-based interface controllers?
- Are there equivalents for UIActivityIndicator or UIAlertController on the Apple Watch?
- Can I use Core Graphics to generate images dynamically and then use them in a watch app? Can they be cached on the watch?
- Can I use custom views in the Apple Watch? Can I customize the interface elements beyond their public API?
- How does the Apple Watch communicate with your iPhone?
- Can I use the Apple Watch while in Airplane Mode?
- What happens to my app when the Apple Watch can’t communicate with its paired iPhone?
- How can a watch app communicate with its companion iPhone app?
- How can an iPhone app communicate with its watch app?
- What happens if I don’t implement static or dynamic notification interfaces?
- What’s the difference between setImage(_:) and setImageNamed(_:)?
- Can I use iCloud in a watch App?
- Animation
- How can I add animations to my watch app?
- Can I create animations for the Apple Watch in code?
- What is the maximum animation frame rate on the Apple Watch?
- 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?
- How can I unit test my WatchKit extension?
- Sharing Data
- How can you share data between a WatchKit extension and its containing iOS app?
- How can you share a Core Data database between a watch app and an iPhone app?
- Let’s Get Down to Business
- Can you make games for the Apple Watch? What kinds of games are suitable?
- How can you earn money with Apple Watch apps?
- 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?
- More Questions?
Under The Hood
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.
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
reply(...)
}
}
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.