Introduction
This year at WWDC, Apple officially unveiled watchOS 3, their latest update to the Apple Watch's core software. While there were only a few "headline" user features shown off, watchOS 3 opens up a lot of APIs for developers to create even more functional watchOS apps. A lot of these APIs have been available on iOS for multiple years and have now been added to watchOS, including CloudKit, SpriteKit, and SceneKit.
In this tutorial, I'll show you how you can use all of these new APIs in your watchOS 3 applications. I'll also show you some of the most significant additions to existing watchOS frameworks.
Prerequisites
This tutorial requires that you are running Xcode 8 on macOS 10.11 or later. It is also assumes that you are comfortable with the basics of WatchKit and developing watchOS apps. If you aren't, then I recommend checking out some of the following tutorials covering the basics of WatchKit:
- WatchKitThis Is What You Need to Know About WatchKit
- WatchKitYour First WatchKit Application: User Interface
- WatchKitYour First WatchKit Application: User Interaction
- WatchKitWatchKit Navigation, Transitions, and Contexts
- WatchKitUnderstanding the WatchKit Layout System
You will also need to download the starter project from GitHub.
1. New Frameworks
SpriteKit and SceneKit
Two of the biggest additions to watchOS 3 for developers are the SpriteKit and SceneKit frameworks. These frameworks provide rich 2D and 3D graphics respectively in Apple Watch applications. You can display scenes in your apps by using the new WKInterfaceSCNScene
and WKInterfaceSKScene
interface objects, which are both subclasses of WKInterfaceObject
. Similarly to SCNView
and SKView
on iOS, these interface objects provide properties and methods to manipulate your scenes, including play/pause functionality as well as default lighting.
Open up the starter project and open up the Interface.storyboard file. You will see that in this file, I have already set up some basic interfaces for you. For this part of the tutorial, we are only interested in the topmost interface controller with a single button. Go to the Object library in the bottom right corner of Xcode and drag in a SceneKit Scene object above the Play / Pause button:
Next, open up the Attributes Inspector and assign the scene file (Scene.scn) included in the project to the Scene property of this interface object:
To work with this in our code, open up the SceneKitInterfaceController.swift file in the Assistant editor and create and link an outlet called sceneItem
for your interface object:
@IBOutlet var sceneItem: WKInterfaceSCNScene!
Please note that in order for your SceneKit content to render correctly, you must link the interface object in your storyboard with an IBOutlet
in your code. At the time of writing this tutorial, it is not mentioned anywhere in Apple's documentation, but this setup is required.
Lastly, to implement the play/pause functionality of our button, replace the existing didPress(button:)
method with the following:
@IBAction func didPress() { if let paused = sceneItem.scene?.isPaused { sceneItem?.scene?.isPaused = !paused } }
Build and run your app and you will see a red cube spinning on the screen:
Pressing the Play/Pause button should stop and start the animation of your scene as needed.
While we just covered displaying SceneKit content in this tutorial, adding support for SpriteKit is very similar. The only major difference is that SpriteKit assets must be used with a WKInterfaceSKScene
object rather than a WKInterfaceSCNScene
object for SceneKit.
UserNotifications
Another addition with iOS 10 and watchOS 3 is the UserNotifications framework. This framework provides a simple way to work with both local and remote notifications being sent and delivered by your application.
If you want to learn more about this framework, check out my tutorial covering it here:
Please note that not all the APIs in the UserNotifications framework on iOS are available in watchOS. Those that are present, however, function identically on watchOS and iOS.
CloudKit, GameKit, CoreAudio, and AVFoundation
Another major addition in watchOS 3 is the availability of frameworks which were previously only on other Apple platforms, including CloudKit, GameKit, CoreAudio, and AVFoundation.
While the full set of APIs from these frameworks aren't available in watchOS, the classes and methods that can be used in Apple Watch apps work identically to their iOS and macOS counterparts.
2. Existing Frameworks
In addition to adding many new frameworks, watchOS 3 also brings about many changes to existing frameworks—including WatchKit and ClockKit.
WatchKit
The first new feature in the WatchKit framework we are going to look at is the new WKCrownSequencer
class. This class allows you to retrieve detailed data about the digital crown, including its current rotation speed and whether or not it is idle. While this information is accessible via properties on a WKCrownSequencer
object, the WKCrownDelegate
protocol enables you to track changes more easily.
All WKInterfaceController
subclasses now have a crownSequencer
property, which is an instance of the WKCrownSequencer
class. This means that to track changes in the digital crown, you only have to specify a delegate object and implement the methods you want.
In your project, open up your CrownInterfaceController.swift file and make your CrownInterfaceController
class conform to the WKCrownDelegate
protocol:
class CrownInterfaceController: WKInterfaceController, WKCrownDelegate { ... }
Next, replace your current awake(withContext:)
method with the following:
override func awake(withContext context: Any?) { super.awake(withContext: context) crownSequencer.delegate = self crownSequencer.focus() }
In the above code, we call the focus
method on the crownSequencer
because otherwise it will not receive events from the digital crown. If an item in your interface gets focused by the user tapping on it then you will need to call this method again for the crownSequencer
to detect digital crown movement.
Lastly, add the following two methods to your class:
func crownDidRotate(_ crownSequencer: WKCrownSequencer?, rotationalDelta: Double) { if let speed = crownSequencer?.rotationsPerSecond { label.setText("Crown\nspeed:\n\(speed)") } } func crownDidBecomeIdle(_ crownSequencer: WKCrownSequencer?) { label.setText("Crown\nis idle") }
So that this interface is loaded, open up your Interface.storyboard file and drag the Initial Controller arrow to select the bottom interface:
Build and run your app and you will see that, when the watch's digital crown is moved, the on-screen label reflects the current status:
If you are using the Apple Watch simulator, then you can "turn" the digital crown by just scrolling with your Mac's mouse or trackpad.
In addition to detecting digital crown movements, the WatchKit framework in watchOS 3 also provides the following classes for your app to detect gestures without using interface items:
WKLongPressGestureRecognizer
WKPanGestureRecognizer
WKSwipeGestureRecognizer
WKTapGestureRecognizer
As their names suggest, these gesture recognisers work very similarly to the way gesture recognisers work on iOS. These classes are particularly useful to detect touches if you're using SceneKit, SpriteKit or a custom image-based interface to display content.
ClockKit
watchOS 3 also brings a few new important features for apps that take advantage of the ClockKit framework to provide complications on the watch face.
Firstly, because of the new background processing functionality for apps in watchOS 3, if a user puts one of your app's complications on their watch face, then your app will remain in memory and remain in a ready-to-launch state. Additionally, your app is guaranteed to be able to update its content in response to push notifications up to 50 times per day.
If you want to learn more about the new background app functionality in watchOS 3, I have already covered this topic here:
Next, some new templates have been added to the extra-large complication family, including CLKComplicationTemplateExtraLargeColumnsText
, CLKComplicationTemplateExtraLargeRingImage
, CLKComplicationTemplateExtraLargeRingText
, and CLKComplicationTemplateExtraLargeSimpleImage
.
Lastly, the CLKTextProvider
class now provides an API to create a localisable text provider to use different text for specific device regions.
Apart from these small additions, ClockKit remains unchanged from last year's watchOS 2 release. If you want to learn more about this framework and how to use it yourself, you can check out my tutorial covering it here:
PassKit
While PassKit was already available in a limited form in watchOS 2, watchOS 3 brings full support for in-app Apple Pay purchases right on the watch. This is done through some new classes and a protocol, including:
-
WKInterfacePaymentButton
: used to show a pre-designed Buy with Apple Pay button. -
PKPaymentAuthorizationController
: used to display a model interface with payment information for the user to confirm. This class performs the same role as thePKPaymentAuthorizationViewController
class but does not depend on UIKit. This means that thePKPaymentAuthorizationController
class can be used on both iOS and watchOS. -
PKPaymentAuthorizationControllerDelegate
: classes can be made to conform to this. This protocol allows your app to respond to the user's actions regarding your payment, including when they select a payment method or when the payment has been authorised.
Conclusion
Overall, watchOS 3 is a significant release for developers of Apple Watch apps. Games and media-rich applications are now far easier to create with the addition of frameworks, including SceneKit, SpriteKit, GameKit, and AVFoundation. The addition of CloudKit and improvements to WatchKit, ClockKit and PassKit allows you to create more functional apps than ever before while becoming more independent of the iPhone.
As always, please be sure to leave your comments and feedback in the comments section below. For a closer look at how to create an app in WatchOS, check out the watchOS 2 From Scratch course here on Envato Tuts+.
Comments