An Overview of the WatchKit App Architecture

PreviousTable of ContentsNext
Building an Example WatchKit AppAn Example Interactive WatchKit App using Actions and Outlets


Purchase the fully updated watchOS 2/Swift 2 edition of this book in eBook ($12.99) or Print ($27.99) format
watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters.

Buy Print


The previous chapters have explained that a WatchKit app consists of two main components, the WatchKit app itself residing on the Apple Watch and the WatchKit extension installed on the iPhone device. We have also established that the wireless communication between the WatchKit app and the WatchKit extension is handled transparently by the WatchKit framework.

It has also been established that the WatchKit app is primarily responsible for displaying the user interface while the programming logic of the app resides within the WatchKit extension.

It is less clear at this point, however, how the user interface elements in the app are connected to the code in the extension. In other words, how the project is structured such that tapping on a button in a scene causes a specific method in the extension to be called. Similarly, we need to understand how the code within the extension can manipulate the properties of a visual element in a storyboard scene, for example changing the text displayed on a Label interface object. These topics will be covered in this chapter and then put into practice in the next chapter entitled An Example Interactive WatchKit App using Actions and Outlets.

This chapter will also provide an overview of the lifecycle of a WatchKit app and outline the ways in which this can be used to perform certain initialization tasks when a WatchKit app is launched.

Basic WatchKit App Architecture

As discussed in previous chapters, the WatchKit app itself consists only of the storyboard file and a set of resource files. The storyboard contains one or more scenes, each of which represents a different screen within the app and may, optionally, provide mechanisms for the user to transition from one scene to another. Clearly this does not provide any functionality beyond presenting user interfaces to the user. The responsibility of providing the behavior behind a user interface scene so that the app actually does something useful belongs to the interface controller.

WatchKit Interface Controllers

Each scene within a storyboard must have associated with it an interface controller instance. Interface controllers are subclassed from the WatchKit framework WKInterfaceController class and contain the code that allows the WatchKit app to perform tasks beyond simply presenting a user interface to the user. This provides a separation between the user interfaces (the storyboard) and the logic code (the interface controllers). In fact, interface controllers are similar to view controllers in iOS applications.

The interface controllers for a WatchKit app reside within the WatchKit extension associated with the app and are installed and executed on the iPhone device with which the Apple Watch is paired. It is the responsibility of the interface controller to respond to user interactions in the corresponding user interface scene and to make changes to the visual elements that make up the user interface. When a user taps a button in a WatchKit scene, for example, a method in the interface controller will be called by the WatchKit framework in order to perform some form of action. In the event that a change needs to be made to a user interface element, for example to change the text displayed on a label, the interface controller will make the necessary changes and the WatchKit framework will transmit those changes to the WatchKit app where the update will be performed.

This sounds good in theory but does not explain how the connections between the elements in the user interface on the watch device and the interface controller on the iPhone are established. This requires an understanding of the concepts of outlets and action methods.


WatchKit Action Methods

Creation of a WatchKit app typically involves designing the user interface scenes using the Interface Builder tool and writing the code that provides the logic for the app in the source code files of the interface controller classes. In this section we will begin to look at how the user interface scene elements and the interface controller code interact with each other.

When a user interacts with objects in a scene of a WatchKit app, for example touching a button control, an event is triggered. In order for that event to achieve anything, it needs to trigger a method call on the interface controller class. Use of a technique known as target-action provides a way to specify what happens when such events are triggered. In other words, this is how you connect the objects in the user interface you have designed in the Interface Builder tool to the back end Swift code you have implemented in the corresponding interface controller class. Specifically, this allows you to define which method of the interface controller gets called when a user interacts in a certain way with a user interface object.

The process of wiring up a user interface object to call a specific method on an interface controller is achieved using something called an Action. Similarly, the target method is referred to as an action method. Action methods are declared within the interface controller class using the IBAction keyword, for example:

@IBAction func buttonPress() {
    println("Button Pressed")
    // Perform tasks in response to a button press
}

WatchKit Outlets

The opposite of an Action is an Outlet. As previously described, an Action allows a method in an interface controller instance to be called in response to a user interaction with a user interface element. An Outlet, on the other hand, allows an interface controller to make changes to the properties of a user interface element. An interface controller might, for example, need to set the text on a Label object. In order to do so an Outlet must first have been defined using the IBOutlet keyword. In programming terms, an IBOutlet is simply an instance variable that references the user interface object to which access is required. The following line demonstrates an outlet declaration for a label:

@IBOutlet weak var myLabel: WKInterfaceLabel!

Once outlets and actions have been implemented and connected, all of the communication required to make these connections work is handled transparently by WatchKit. Figure 4-1 provides a visual representation of actions and outlets:


WatchKit actions and outlets diagram

Figure 4-1


Outlets and actions can be created visually with just a few mouse clicks from within Xcode using the Interface Builder tool in conjunction with the Assistant Editor panel, a topic which will be covered in detail in the chapter entitled An Example Interactive WatchKit App using Actions and Outlets.

Purchase the fully updated watchOS 2/Swift 2 edition of this book in eBook ($12.99) or Print ($27.99) format
watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters.

Buy Print

The Lifecycle of a WatchKit App

The lifecycle of a WatchKit app and the corresponding WatchKit extension is actually very simple. When a WatchKit app is launched on the device, a scene will be loaded from within the storyboard file. When the scene has loaded, the WatchKit framework will request that the extension corresponding to the app be launched on the iPhone device (or woken up if it is currently suspended). The extension is then instructed to create the interface controller associated with the scene that was loaded.

As long as the user is interacting with the WatchKit app the extension will continue to run on the iPhone. When the system detects that the user is no longer interacting with the watch, or the user exits the app, the interface controller is deactivated and the extension suspended.

At various points during this initialization and de-initialization cycle, calls will be made to specific lifecycle methods declared within the interface controller class where code can be added to perform initialization and clean up tasks. These methods are as follows:

  • init() - The first method called on the interface controller when the scene is to be displayed. This method can be used to perform initialization tasks in preparation for the scene being displayed to the user. It is also possible to make changes to user interface objects via outlets from within this method.
  • awakeWithContext() - This method is called after the call to the init() method and may optionally be passed additional context data. This is typically used when navigating from one scene to another in a multi-scene app and allows data to be passed from the interface controller of the currently displayed scene to the interface controller of the destination scene. Access to user interface objects is available from within this method.
  • willActivate() – Called immediately before the scene is presented to the user on the Apple Watch device. This is the recommended method for making final minor changes to the elements in the user interface. Access to user interface objects is available from within this method.
  • didDeactivate() – The last method called when the user exits the current scene or the system detects that, although the app is still running, the user is no longer interacting with the Apple Watch device. This method should be used to perform any cleanup tasks necessary to ensure a smooth return to the scene at a later time. Access to user interface objects is not available from within this method. Calls to this method may be triggered for testing purposes from within the WatchKit simulator environment by locking the simulator via the Hardware -> Lock menu option.

The diagram in Figure 4-2 illustrates the WatchKit app lifecycle as it corresponds to the WatchKit extension and interface controller:


The WatchKit app lifecycle diagram

Figure 4-2


It should be noted that, with the exception of the app launch and extension suspension phases in the above diagram, the same lifecycle sequence is performed each time a scene is loaded within a running WatchKit app.

WatchKit Extension Guidelines

A key point to note from the lifecycle description is that the WatchKit extension is suspended when the user either exits or stops interacting with the WatchKit app. It is important, therefore, to avoid performing any long term tasks within the extension. Any tasks that need to continue executing after the extension has been suspended should be passed to the containing iOS app to be handled. Details of how this can be achieved are outlined in the WatchKit App and Parent iOS App Communication chapter of this book.

Summary

Each scene within a WatchKit app has associated with it an interface controller within the WatchKit extension. The interface controller contains the code that provides the underlying logic and behavior of the WatchKit app. The interactions between the current scene of a WatchKit app running on an Apple Watch and the corresponding interface controller within the WatchKit extension are implemented using actions and outlets. Actions define the methods that get called in response to specific actions performed by the user within the scene. Outlets, on the other hand, provide a mechanism for the interface controller code to access and modify the properties of user interface objects.

When a WatchKit app is launched, and each time a new scene is loaded, the app has a lifecycle consisting of initialization, user interaction and termination. At multiple points within this lifecycle, calls are made to specific methods within the interface controller of the current scene thereby providing points within the code where initialization and de-initialization tasks can be performed.


Purchase the fully updated watchOS 2/Swift 2 edition of this book in eBook ($12.99) or Print ($27.99) format
watchOS 2 App Development Essentials Print and eBook (ePub/PDF/Kindle) editions contain 35 chapters.

Buy Print



PreviousTable of ContentsNext
Building an Example WatchKit AppAn Example Interactive WatchKit App using Actions and Outlets