The news on Apple Watch ordering day when I rose at 6:30 US/Eastern was that the first production run had sold out — which I expected. Unexpected was that I found one (and only one!) style available for first wave delivery. The watch arrived April 24 (Friday) via UPS as promised.
Time to Code!
On Friday I enjoyed using the Apple Watch, and realized that this really is a product the world needs. But by Saturday the only thing on my mind was what to code for the Watch!
What’s Robot Runner?
Robot Runner is one of my internal test apps. I use it for working with Bluetooth techniques. It’s a fun app since it has sensors, animation and involves some hardware hacking with an Arduino module and breadboard.
Robot Runner is an iPhone app written with Swift in XCode that connects to an embedded controller (the Arduino board) using Bluetooth Low Energy (a BLE shield attached to the Arduino). The architecture of the app is in the diagram below.
The iPhone app starts and stops the robot, and reads temperature and ambient light intensity sensors on the robot. It’s a good hacking solution since it incorporates many different elements used in mobile connected device applications.
Robot Runner Apple Watch Design Objective
For the Watch project, the objective is to add a to the existing app the ability for the user to connect to the Robot using the Watch instead of the iPhone. This is a typical use case for the Apple Watch — giving the user the ability to use the core functions of the app from the watch. The final architecture will be as follows:
Currently, all 3rd-party apple Watch apps are built as extensions to iPhone apps. In the diagram above, it’s not (yet) possible to eliminate the iPhone entirely, but it is possible to leave the phone in standby (in a pocket or purse, or in the next room) and let the watch wearer still use the app functions.
The Watch app remains connected to the iPhone through a Bluetooth “umbilical cord”. In MVC terms, the Models and Controller are still resident in the phone, and only the View is resident on the watch. Maybe that will change in the future, but for now, it makes sense. Leaving the Controller on the iPhone certainly will conserve the watch’s battery and CPU.
A significant part of Robot Runner is the code to scan for the Bluetooth devices, connect to them, and once connected send commands and read sensor values. In the current iPhone app (Robot Runner.app, in purple within the below diagram), all of the code used by the iPhone app is contained within the single iPhone app target.
The Watch app (Robot Runner WatchKit.app, in blue), won’t connect directly to the Arduino module’s Bluetooth interface, but will do so via the Robot Runner WatchKit Extension.app (green), which runs on the iPhone. So far so good. But there’s a wrinkle that requires some re-architecting.
Once the Apple Watch is added to the solution, the two Bluetooth modules (BTDiscoverySvc.swift and BTPeripheralSvc.swift) will need to be used by Robot Runner.app and Robot Runner Watchkit Extension.app. However, although these apps are installed together, they run in different sandboxes. So, we either need to compile and link the two Bluetooth swift modules into both targets, or break them out into a common framework. The framework is easier to maintain and reduces the runtime footprint, so I chose that path. This framework is called RobotRunner.framework.
This sandbox separation also restricts sharing of data between the Apple Watch and iPhone controllers. Specifically, the project needs to have a single app group with entitlements granted to both the iPhone app and Watch Extension targets. Using the app group, the iPhone app and watch extension can share data using flat files, Core Data/SQLite and/or NSUserDefaults. Robot Runner does’t need a shared data capability (yet), so this wasn’t a factor in this project.
Putting the pieces together
With the refactoring of common code into the framework, the rest of the development is straightforward. The logic to connect to and communicate with the Robot’s Bluetooth controller was expressed in the Robot Runner WatchKit Extension.app, and the UI was designed in the Robot Runner WatchKit.app.
I’m happy to report that no significant challenges were encountered. There are differences between UIKit used for the iPhone UI and WatchKit used for the Watch UI, and the controller lifecycle states are named differently (and there are fewer of them). So, certainly, there’s a learning curve for existing iOS developers.
I expected challenges with the Core Bluetooth modules and delegates (either because of the WatchKit controller or the re-factoring into the Framework), but I was pleasantly surprised not to encounter any unusual challenges. A little bit of change related to the framework refactoring, but overall all of the Core Bluetooth code worked as-is.
The Final Results
Here’s a side-by-side (or over/under if you’re on a phone device) comparison of the UI for the iPhone and Apple Watch versions of Robot Runner. Note that in moving from the 4.7″ iPhone screen to the 38mm-42mm watch screen there has been no loss of functionality.
All of the same information is displayed. The command button and sensor outputs are still on the same screen together. Even the animated Robot renders exactly the same using the same frame images (he runs when the robot is in a run state, and is stopped when the robot is in a stopped state).
Apple has done a great job of keeping the basic developer workflow relatively consistent with WatchKit. Learning WatchKit isn’t much more challenging than learning any unfamiliar framework. No doubt this relatively modest learning curve has something to do with the App Store having so many apps ready-to-go on the day the Watch first shipped (reports indicated there are already thousands!).
Originally published at rekerrsive.ghost.io on April 27, 2015.