Apple WatchKit gives you a choice when it comes to navigation. You can be Page-based as we introduced in our last lesson. Another alternative, is hierarchical interfaces, which closely resemble navigation controllers on the phone. In this lesson, we’ll introduce the hierarchical type of navigation by setting up a small app.
Hierarchy Controllers
Pages are linear while hierarchical interfaces are tree like. They can branch depending on interaction with the user. They also more easily share data through a value called a context.
Make a new single-view project in Xcode using Swift called SwiftNavigationDemo. Once it loads, Select an Apple Watch WatchKit App for this application.
We will not use notifications. In the next window, make sure both glances and notifications are checked off.
Click Finish and then Activate. In the navigator, find the WatchKit App group. Open the Interface.storyboard.
You will have an empty storyboard with one controller. In the object inspector, find the Interface controller, which should be at the top of the list.
Drag three interface controllers to the storyboard, placing them next to each other like this:
Select the main interface. In the Attribute inspector, set the title and Identifier to Main
Do the same for the other two controllers, naming the upper one Up Branch and the lower one Down Branch. Your storyboard should look like this :
On the main controller, add two buttons. Title one button Up and the other button Down. Position the Up button Horizontal center and Vertical top. Position the Down button as Horizontal Center and Vertical Bottom.
Control-drag from the Up button to the Up Branch interface until the interface highlights.
Release the mouse button. You get a menu of segues. Select push.
You get a segue from the button to the interface.
Notice that the segue menu was context sensitive. When you control drag from a button, you get the two action segues of push and modal. When you control dragged from interface to interface in the last lesson, you got a page segue.
The up branch interface now has a back arrow to return us to the previous controller.
Control drag from the Down button to the Down branch interface, and select push. Your storyboard should look like this:
Build and run. We get the two buttons.
press the Up button.
Tap the < to go back to the main interface. Press the Down button. Our app works.
Notice that our titles get compressed when the time appears on the watch. It is a good idea to keep titles very short.
If you only are interested in navigation, segues are good enough. As an exercise, add two more interfaces by segues to the bottom controller.
Programmatic Hierarchical Interfaces
You can begin to see that you can get complex user interfaces using a hierarchy. You can use a programmatic approach to hierarchical interfaces for even more power.
We will need a new view controller on the extension to do this. When adding view controllers for the watch, it is vital the controller be on the extension, not the phone bundle or the watch app. Press Command-N to get a new file. Select a new Cocoa Touch class. Make a file named UpInterfaceController subclassing WKInterfaceController
In the next step be careful. When you save the file, Xcode may assume this is a file for the WatchKit app. You might see it wants to save to the WatchKit App.
It also wants to assign it to the wrong group and target.
Select the group drop down menu and change the group to the extension’s group
The file’s location and targets will change to show this. Click Finish. The file stores in the correct place.
Go to the watch storyboard. Select the Up Branch interface. go to the identity inspector and change the class to UpInterfaceController.
Add a button to the top, a switch in the center and a switch on the bottom . Title the button Go!, the middle switch Gray and the bottom switch Dark like this:
Add two more interfaces to the storyboard. In the attributes inspector set the Identifier and Title to Gray. On the Dark switch, set the identifier and title to Color. On the Gray, set the background color to Dark Gray. On the color, set the background for a dark blue or red-blue color of your choice . I used hex #440088 in the color chooser.
Once done, your storyboard should look like this:
Add two more controllers. Press Command-N and add another WKInterfaceController
named GrayInterfaceController, once again making sure you change the group to the Extension. Once done, add one more WKInterfaceController
to the extension named ColorInterfaceController. In the identity inspector make the class of the Gray Interface GrayInterfaceController
and the color interface ColorInterfacecontroller.
Open the assistant editor and select the Up Branch interface.
Control-drag from the gray switch to the code and make an outlet named navigationSwitch. Control-drag from the dark switch and make an outlet named colorSwitch. Adding a comment to mark your outlets, you should now have this in your code
//MARK: - Outlets @IBOutlet weak var colorSwitch: WKInterfaceSwitch! @IBOutlet weak var navigationSwitch: WKInterfaceSwitch!
Now add an action for the button named goButtonPressed. Add an action from the Gray switch named navigationSwitchdidChange. Add an action from the color switch named colorSwitchDidChange. You should have the following when done:
@IBAction func navigationSwitchDidChange(value: Bool) { } @IBAction func colorSwitchDidChange(value: Bool) { } @IBAction func goButtonPressed() { }
WatchKit is write only. There are no properties on the controls we can read. We’ll need to store the switch state in the extension. Add two Bool
values above the outlets:
var isGoingToGray = true var isDarkColor = true
Change the code for navigation switchDidChange
to this:
@IBAction func navigationSwitchDidChange(value: Bool) { if value{ navigationSwitch.setTitle("Gray") }else{ navigationSwitch.setTitle("Color") } isGoingToGray = value }
We change our title and save our state. We do the same with the colorSwitchDidChange
action. Change it to this:
@IBAction func colorSwitchDidChange(value: Bool) { if value{ colorSwitch.setTitle("Dark") }else{ colorSwitch.setTitle("Light") } isDarkColor = value }
That is all setup for the go button, which will logically go to one of the two interfaces. It will also pass a Bool
value to the destination controller.
Change the goButtonPressed
to this:
@IBAction func goButtonPressed() { //prepare context var myContext:Bool? = isDarkColor //logical navigtion if isGoingToGray { pushControllerWithName("Gray", context: myContext) }else{ pushControllerWithName("Color", context: myContext) } }
The important line here is the pushControllerWithName("Color", context: myContext)
statement, which pushes a new controller onto the navigation stack. We first prepare a value called a context to pass to the destination controller. We check which interface we want, the color or gray one. We push that controller onto the display stack using the storyboard identifier instead of a segue to the watch. We also pass the Bool
value to the destination.
Build and Run. The switch logically selects the correct interface.
We sent data to the destination controllers, but we didn’t do anything with it. In our next lesson, we’ll pass and use data between controllers using the context.
Leave a Reply