With the initial release of the WatchKit SDK expected later this month, it’s not too early to start thinking about apps you might want to work on.
How can you add a small-screen component to your own apps? And what kinds of new apps can you think of that really take advantage of the watch and all its features?
We know we won’t get WatchKit until later this month, and won’t see any actual hardware until 2015, but what if you want to start preparing in advance?
Good news: to help us get started early, I have written a Watch Simulator template app that can run on iPhone and iPad! You can use the familiar interface builder tools, storyboards, and Swift code to build a prototype Apple Watch app.
In this tutorial, you’ll use the watch simulator to get a feel for what the hardware will be like. The actual WatchKit SDK might be quite different, but this at least helps you prototype some ideas, allowing you to get a good head start.
Getting Started
Apple Watch has a few nifty features that you’ll want to keep in mind as you dream up apps for it. It has a flexible display that can distinguish the difference between a light tap and a hard press, known as Force Touch. This might be useful in a space-based shooter game; taps could shoot the machine-gun, and a hard press fire a missile.
Apple Watch also has a scroll wheel on the side that is known as the Digital Crown. By spinning it, you can collect one-dimensional movement information to zoom maps and images, or scroll through a list.
The vibration motor is extremely precise. You’ll be able to feel different parts of the backface face vibrate, so for example if you are using it for GPS directions, you could feel the difference between a right turn and a left turn vibration.
Finally, Apple Watch has a sensor that uses infrared, visible-light LEDs and photodiodes to detect your heart rate. In the prototype app for this tutorial, you’re going to build something that makes use of the heart rate sensor.
Watch Simulator
You’ll use the Watch Simulator template project to provide a nice place to start. Download the Watch Simulator project, unzip the file, and open WatchSimulator.xcodeproj in Xcode.
Open Main.storyboard by selecting it in the File Navigator.
You’ll see a simulated watch in the Main View Controller Scene and an embedded App View Controller Scene that will hold the user interface for your app. As you set up the UI, remember to add all the views to the App View Controller scene!
First, you’ll set up the label that will show the user’s heart rate. Drag a Label from the object library to the App View Controller.
With the label selected, open the Attributes Inspector and change the label’s text to 80 (the text, not the font size).
Then open the font popup and change Font to Custom, and then the rest of the settings to Helvetica Neue, Light, and a size of 32.
Next, update Color to white, with 60% opacity.
Click the Pin button in the lower right, which looks like a TIE fighter, for the Star Wars fans. Uncheck Constrain To Margins. Set the right constraint to 4 and the bottom constraint to -1 – that is indeed negative. Change Update Frames to Items of New Constraints.
Finally, click Add 2 Constraints to add the constraints and update the layout.
You should see the label move to the bottom-right of the view.
Since the user’s heart rate will change, you’ll need to connect an outlet so you can change the value from code.
Open the Assistant Editor and make sure AppViewController.swift is open in the editor; if it’s not then select it from the jump bar at the top. Control-drag from the label to a spot inside the class definition.
Name your outlet bpmLabel
and hit Connect.
Good work! Now you have your completed view.
Creating the Model
Now that view is set up, the next step is to model the data. You’ll need some place to store the heartbeat data – for this app, that’ll consist of an icon, some descriptive text, and the actual beats per minute value.
In the Project Navigator, right-click the WatchSimulator group and select New File…. Select the iOS\Source\Swift File template and click Next.
Name the file BeatPattern.swift and click Create.
Make sure BeatPattern.swift is open and replace the contents with the following:
import UIKit struct BeatPattern { var icon = "" var description = "Mid-range" var bpm = 80 } |
This sets up the previously-mentioned properties for the struct. You’ll be using emoji rather than an image for the icon, so that’s a String
rather than an instance of UIImage
.
Next, add the following computed property to the bottom of the struct:
var duration: Double { return 60.0 / Double(bpm) } |
This property tells you how much time each heartbeat takes. For the math nerds amongst you, here’s how this is derived:
60 seconds/minute ÷ X beats/minute = Y seconds/beat
That’s all you’ll need for the model! Since you’ve provided default values for the properties, you don’t need to explicitly define an initializer. Swift will automatically create an initializer with the init(icon:description:bpm:)
signature, which you’ll use to provide your own values.
Displaying Heartbeats
The app will show different icons depending on the user’s heart rate, so you’ll need to define those ranges next.
Open AppViewController.swift and add the following array property to the class:
There’s some emoji there for the icons, and web browsers can have trouble displaying those characters. Instead, here’s a text file with the code snippet above. You can download it, open it in a text editor, copy it, and paste it directly into AppViewController.swift.
Next, add the following two properties to the class:
var currentBeatPattern = BeatPattern() var currentBeatPatternIndex = 0 |
This will store the current beat pattern using the struct you just defined, as well as which beat pattern to use by storing the necessary index of the beatPatterns
array.
You’ll need a label to show the emoji icon. Rather than use the storyboard, you can set that up in code. Add another property to the class:
let iconLabel = UILabel() |
Now that you have the label, you’ll need to set it up and add it to the view. Add the following line to the end of viewDidLoad
:
self.view.insertSubview(iconLabel, atIndex: 1) |
This will add the icon label to the view. To set up the label, add the following method next:
override func viewWillAppear(animated: Bool) { super.viewWillAppear(animated) iconLabel.frame = self.view.bounds iconLabel.textAlignment = .Center iconLabel.font = UIFont.boldSystemFontOfSize(132) } |
This will set the icon label to be as big as the entire watch screen. Since the display will be a single emoji character, you’ll need a large font size of 132 points to get this to look just right.
You might wonder why this code can’t go in viewDidLoad
. Although the view is loaded at that point, the subviews are not quite in place yet. By waiting just a bit longer for the call to viewWillAppear(animated:)
, you make sure that you cad add the new views and place them correctly.
Since this is just a simulation, you’ll cycle through the available beat patterns in sequence. Add the following method to the class to handle the cycling:
func newBeat() { // 1 if ++currentBeatPatternIndex == beatPatterns.count { currentBeatPatternIndex = 0 } // 2 currentBeatPattern = beatPatterns[currentBeatPatternIndex] // 3 bpmLabel.text = "\(currentBeatPattern.bpm)" iconLabel.text = currentBeatPattern.icon } |
Here’s what’s going on in this method, step-by-step:
- First, you increment the current index to switch to the next beat pattern. If you’ve reached the end and the new index is out of the range of the array, reset the index to zero to start from the beginning.
- With the new index, you set
currentBeatPattern
using the array. - Set the values for the two labels in the view. Notice that you’re using Swift’s string interpolation to convert the Int into a String.
For now, you’ll simulate a changing heartbeat by adding a timer to call newBeat()
periodically. Add the following method to the class:
override func viewDidAppear(animated: Bool) { super.viewDidAppear(animated) newBeat() NSTimer.scheduledTimerWithTimeInterval(8, target: self, selector: Selector("newBeat"), userInfo: nil, repeats: true) } |
This will call newBeat()
once to kick things off, and then set up a timer to call newBeat()
every eight seconds beyond that to update the view.
Now, build and run. Every eight seconds, you will see the color of the heart change and the beats-per-minute number update.
Animating the Heartbeat
The final thing is to do something interesting in those eight seconds, namely a little animation to make the heartbeat look realistic. Remember, the watch will have sensors to detect the actual heart rate, so showing live data like this is a nice touch!
Add two more properties to the class:
let shrinkFactor = CGFloat(2.0 / 3) var expandFactor: CGFloat { return 1.0 / shrinkFactor } |
The shrinkFactor
is how much the heart will contract in an animation. The expandFactor
is just the inverse of the shrinkFactor
, which you’ll use for the second half of the animation.
By doing it this way you ensure that the heart never looks pixelated. Imagine you have an image that is 500 pixels. If you shrink it down to 300 and then return to to 500, you never go beyond the original resolution and you keep the image sharp. Although Emoji is a vector font, when it is rendered in the label, it gets treated as pixels just like any other image.
Next, add the following method to the class to perform the actual animation:
func beat() { // 1 UIView.animateWithDuration(currentBeatPattern.duration / 2, delay: 0.0, options: .CurveEaseInOut, animations: { // 2 self.iconLabel.transform = CGAffineTransformScale( self.iconLabel.transform, self.shrinkFactor, self.shrinkFactor) }, completion: { _ in // 3 UIView.animateWithDuration(self.currentBeatPattern.duration / 2, delay: 0.0, options: .CurveEaseInOut, animations: { // 4 self.iconLabel.transform = CGAffineTransformScale( self.iconLabel.transform, self.expandFactor, self.expandFactor) }, completion: { _ in // 5 self.beat() } ) } ) } |
There are animations nested in animations here for the full effect! Here’s what’s going on in this method:
- The outer animation is the first half of the whole effect, so its duration is half the total duration. You also use
.CurveEaseInOut
animation easing because it makes the beat feel more natural. - Inside the animation closure, transform the heart to it’s shrunken size.
- When the expand animation completes you want to kick off the second half, which is another animation. This again has half the total duration.
- Inside the second animation closure, the difference is you’ll use the
expandFactor
instead of theshrinkFactor
. - Finally, in the completion block of the second animation you have a recursive call to
beat()
. After one cycle completes, another begins.
All that’s left is to start the animation. Add the following line to the end of viewDidAppear
:
beat() |
That will kick off the recursive beat as soon as the view appears.
Build and run. When the simulator opens, you’ll see the heart beating. And again, after eight seconds it will move on to a new pattern.
Notice how the animation speed scales to the current heart rate too. Very realistic!
Where to Go From Here?
You can download the final project for this tutorial in case you got stuck along the way.
There are many additions you could make to this sample app:
- Add another label for the description of the beat pattern.
- Give the heart a random beat instead of going in through the beat patterns in order
- Add and handle an erratic heartbeat. Hint: use a random duration each beat
- Give the user a view of their average heartbeat over time
- And finally, if you want a real challenge, draw a rhythm strip graph of the beats
The simulator is a great tool to get you thinking about what kinds of apps you can build on such a small screen. You can use the empty starter project for this tutorial, or check out the Watch Simulator project on GitHub, which has a simple tap counter as a starter app.
You can use the Watch Simulator project to practice your ideas ahead of the release of WatchKit. WatchKit is rumoured to be released soon after this post. If you’d like to build your own apps and challenge yourself, check out the WatchKit Hackathon scheduled for November 23, 2014.
I hope you’ve enjoyed this tutorial, and welcome to the world of WATCH! :]
Preparing for the Apple Watch: a Prototype Heartbeat App is a post from: Ray Wenderlich
The post Preparing for the Apple Watch: a Prototype Heartbeat App appeared first on Ray Wenderlich.