With the appearance of the WatchKit SDK (https://developer.apple.com/watchkit/) a lot of iOS developers started experimenting with it and writing articles about the challenges faced during development.
Following this trend, in this article we describe our first impression after tackling the WatchKit SDK head-on and the technical challenges encountered while creating a navigation enabled watch app using our Scout SDK .
As you can see from the diagram below, a watch app has two parts: an extension which is running on the phone and the watch app which is running on the iWatch. The watch app contains just the user interface of the app - a simple storyboard file and static images which are displayed in the Watch app's user interface.
The interface objects displayed on the watch are not UIView inherited objects, they are proxy objects inherited from the NSObject class. This means that no custom rendering and animations can be done on the watch.
Currently, the customization of these objects is very limited compared with the UI objects used on an iPhone app. For example, only the text and the colour of a label can be changed in the watch app interface while on the phone there are a lot of other customization possibilities (this might change in the next version of the WatchKit SDK)
The user interface of the watch app can be updated through the extension running on the phone. The extension can communicate with the iWatch app through the declared outlets linked with the iWatch UI objects - all the logic behind the scenes is on the extension.
Let's get started to create our watch app:
For getting started with WatchKit you should have installed the 6.2 Beta version of Xcode.
To add a watch app target to an existing project add a new Watch App target (File -> New target)
Select the Watch app target and run the code. Make sure that one of the external displays of the simulator is selected.
Before going to the next chapter, one more thing should be done. The communication between the iOS app and the WatchKit extension is possible only by using a shared file.
Return to Xcode and configure the bundle identifiers for each target based using the app id configured on the developer portal.
WatchKitDemo: com.skobbler.WatchKitDemo
WatchKitDemo WatchKit Extension:
com.skobbler.WatchKitDemo.watchkitextension
WatchKitDemo Watch App:
com.skobbler.WatchKitDemo.watchapp
7.Select the Capabilities tab of the iOS & Watch app targets. Navigate to the App Groups section and enable it. You should see the following:
First, a look at what the end result looks like:
The WatchKitDemo app starts navigation between two locations on the map, using the Scout SDK. With the app running on the watch and the extension and iPhone app on the smartphone, users can see visual advices and the distance to them.
When the screen of the watch is tapped, an image of the map with the route and current position is shown. This image is updated every few milliseconds.
The iPhone app and the extension communicate via a shared file. For this, developers must enable AppGroups in iTunes Connect and configure the bundle identifiers for each target.
Because there is no API for directly communicating between the iPhone app and the extension we initially wanted to use a timer (NSTimer) to update the information displayed on the Watch every few milliseconds.
The challenge here was that we were not notified when the shared file was modified. The workaround was to use a MMWormhole object. It notified both the app and the extension when the shared file is changed, so the timer was no longer needed.
The MMWormhole object must be initialized both in the iPhone app and in the extension:
self.wormHole = [[MMWormhole alloc] [initWithApplicationGroupIdentifier:@"group.WatchKitDemoGroup"]
(mailto:initWithApplicationGroupIdentifier:@"group.WatchKitDemoGroup") optionalDirectory:nil];
To send and receive data between the app and the extension use:
//send message from the app to the extension
[self.wormHole passMessageObject:imageData identifier:\@"image"];
//listen for messages in the extension
[self.wormHole listenForMessageWithIdentifier:\@"image" listener:\^(id
messageObject{}];
This app we created is a proof of concept of what a developer is able to do with the Scout SDK and the WatchKit SDK. A few scenarios that would be also possible:
display the map (demoed in the app)
show annotations
calculate and present routes
navigation (in the demo app you have an example of turn by turn navigation with visual advices)
perform & show search results
download map packages which can be used offline
display routes based on GPX files
The full demo project can be downloaded and reviewed from:
http://www1.skobbler.com/iphonebuilds/20150116/WatchKitDemo.zip
the WatchKit SDK is quite easy to use and well documented, as expected from a native Apple framework. The development of the WatchKitDemo app took only a single day, without any prior knowledge of the SDK.
one of the biggest weakness of the WatchKit SDK is that the iPhone app should run (foreground or background) while the iWatch app is running, because all the data comes from the iPhone app. We wanted to be able to use the watch app even in the absence of an iPhone.
there is no public API for sending data from the iPhone app to the extension. The only solution is using a shared property list file that contains key-value pairs which can be accessed/ modified at the same time by the two participants.