Dev Notes for Workouts++ 1.0.1

I’ve decided to start writing up informal development notes for each of my significant app updates. My goal is to communicate with my customers about the thinking behind new features. I’ll also throw in a few little technical notes that are perhaps more interesting to the iOS developer community.

Workouts++ 1.0.1

So often when I ship a v1.0 of a new app I am doing it knowing full well that it isn’t perfect. I have found that it is usually more important to ship a solid, useful v1.0 and then start collecting feedback, than it is to agonize over perfection. It might be possible for a larger team to have enough internal discussion and critique to ship a ‘perfect’ v1.0 but for a solo developer that just hasn’t been my experience.

So when I shipped v1.0 on December 21 I knew I’d be turning around a quick update shortly thereafter. Both to add a feature as well as to fix all the little bugs that hadn’t shown up in testing.

The bugs fixed were:

  • It turned out that my method of detecting a user’s preferred units from the Health app didn’t work consistently on the Apple Watch, so I had to manually determine this on the iPhone and sync the setting over.
  • I had initially limited the range of heart rates configurable in the app to a max of 170bpm, but after hearing a lot of feedback from some distinctly impressive athletes this was bumped up to allow them to set their alerts and color thresholds how they needed them.
  • I added Strength, Yoga, Pilates and Functional training types to the available set of workout types. Apple allows for a rather extensive list of possible workout activity types, but to keep things manageable within the app I don’t want to include all of them. So I collected feedback from the initial wave of users to see where I was lacking.
  • The speed/pace calculation system was completely overhauled to avoid situations where the displayed speed would fluctuate wildly. These values aren’t provided directly by the Apple Watch. Instead, I have to derive them from the distance samples I get. The nuances about how often these samples are provided make getting a consistent speed output very tricky. The current mechanism is far more stable and tolerant of fluctuations in the old method. One of the big things I’m working on for v1.1 is location tracking, which will help me gain access to much more accurate avenues for collecting this data. So this is likely an interim fix for now.

The main feature of this update was the ability to Pause workouts. This was intended to be included in v1.0, but I had run into a last minute bug where it wouldn’t consistently update the display when paused so I had disabled the feature for launch.

Superficially pausing had seemed like a straightforward feature to add when I began working on it. But it turns out to be subtly tricky, and in the ways that tend to keep a programmer up at night. Clearly defining what it should do when paused was quite a conundrum for me. Should I keep updating the UI with your heart rate data as it comes in? If you move around while paused should I unpause, add the new distances, or ignore them? How should I handle active calories ‘earned’ while paused for the purposes of totals?

In the end I have initially chosen to take the conservative approach of displaying the data collected while paused, but not automatically resuming based on movement. In my own testing/usage I find that since you can resume with the physical motion of rotating the Crown backwards I have just added that into my muscle memory and rarely forget to resume.

Speaking of which, I reduced the sensitivity of the “rotate crown to end/pause” feature after getting reports that it was too sensitive and had accidentally triggered a few times. The absolute last thing I want to do is loose workout data, which unexpectedly ending a workout would be. Though on the positive side, this is probably the feature for which I have received the most positive feedback for. Turns out I wasn’t the only one annoyed with trying to use their Watch with sweaty fingers.

David Smith