Tag Archives: runcalc

This Old App: Models in the Playgrounds

Back a few months ago, an  app of mine  was removed from the App Store for being too old and not updated enough. In this series of articles I’ll document what I did on rebuilding and improving the app. In our first installment I analyzed the changes necessary. In this second installment,  I’ll start making the model.

I think in Model-View-Controller or MVC. If you are not familiar with MVC, I suggest you take a look at my video in LinkedInLearning on MVC and delegates. In short, a common programming practice is to break an application into three parts: the model, the View and the controller. The model is the code that processes data. The view is the user interface.  We don’t let the view and model interact with each other. Instead we use a controller to coordinate between the two.  This way we can change one while affecting the other two minimally.

While I might get some ideas for the view in my planning stages, I tend to start  coding with the model. In one sense the controller and view are window dressing for the model, where your data is. Views and controllers are the presentation and interaction with that model.

I’ll make a confession here: I hate working on the model. It the most tedious type of programming in my mind. It has none of the glamor or action of views or controllers.  It is just data, and I’m not much of a data person. As such I’ll give you a warning that this is a bit dry, but there’s a lot there to look at, and in the case of  RunCalc, some interesting problems that drove me up the wall the first time I wrote this code.

What’s in the Old Model

Experience in mobile applications has changed me, and the model in the original code was a reminder of this.  Written in Objective-C, The model for version 1.0 was a case of putting all the eggs in one basket.  I did everything in one model.  The original model had four properties to calculate running statistics:

  • Distance
  •  Time
  •  Pace
  • Speed

I added speed to handle treadmill settings, though it is measuring the same thing as pace: How fast the runner is going.

There are four core  methods which derive pace, speed, time and distance.  Basically you can derive each like this:

distance = pace * time

time = distance / pace

pace = time / distance

speed = distance / time

My measurements were seconds for time measurements, which I would format as strings in HH:MM:SS format for display. Distance was in miles. It was easy for me to calculate test cases in miles. I had conversion methods to metric measurements for miles and kilometers.  This meant that I had pace seconds per mile and speed as mile per second, which would have some more conversion to compute it to minutes per mile and miles per hour and kilometers per hour. Metric pace was in kilometers per seconds for some unknown reason that isn’t in my original notes. I think it was laziness.

This was the basics of the model, but there were a few more features that got added to it, The first and most important was the “locking” mechanism. There is a subtle problem with using the formulas above. Suppose you change pace. What do you update, distance or time? If you update both, then your numbers are wrong because things get updated on top of each other, and you can’t change all your settings. For changes in the calculator, what you need is to lock either distance or time in place and only compute one of them when you change pace. I did this with an enumeration in the early version to keep track of what I locked.

The last part of the model was running totals for the splits. It meant I had another set of four properties with totals for distance and time. There were two more for average pace and speed.

Building the new model : Properties and Units

The original had a lot of rounding errors and strange calculations due to switching between kilometers and Imperial measurements. Unlike other measurements systems, there will be a lot of switching between units, particularly in distance, and I really didn’t think this out well the first time. Long distance running uses different distance measurements at the drop of a hat. There are 5K, 8K, 10K, and 15k races. But there are half marathons at 13.1 Miles and full marathons at 26.2 miles. This and other measurements gave me the following measurements:

  • Distance
    • Meters
    • Kilometers
    • Miles
  • Time
    • Seconds
    • Minutes:Seconds
    • Hours:Minutes:Seconds
  • Pace/Speed
    • Meters per second
    • Minutes per mile
    • Minutes per Kilometer
    • Kilometers per hour
    • Miles per hour

Instead of computing in the units I have displayed, I kept with two standard units, meters and seconds, and converted everything else from them. These units match units found in other API’s such as CoreMotion, if I ever decide to interface this with other apps or API’s.

Pace and speed are different ways of describing the same thing, so I made them the same with one measure: Meters per Second.  Everything else  is a conversion.

Derivation Functions and Locking

The derivation function problem the first time took me a month to come up with the enumeration solution. For some reason I could nt wrap my head around the initial problem of handling that many variables.  Version 2.0 will use a different solution the model. There are six methods that change the model, two for each of the three properties. Each one changed one of the two other properties For example for distance:

func distance(changedBy pace:Double) {
    self.distance = distance(pace: pace, time:self.time)
func distance(changedBy time:Double) {
    let newDistance = distance(pace: self.pace, time:time )
    self.distance = newDistance

The Model and Conversions

I built the model as described into two models. One, RunStats for the model described above and one RunStatsIntervals for a collection of RunsStats objects and calculations for finding summations of the collection data. It was here I ran into my problem: The summations would need their own conversions, which were a repeat of the conversions above.

Here’s where object-oriented programming gets its biggest strength: I made up three classes PaceStat, TimeStat, and DistanceStat, that had the conversions. IN stead of using Doubles in my RunStats class I used these three classes. I went one step more and made constructors that would work in any unit I wanted, making the result the correct unit.  For example here’s distance:

public class DistanceStat{
// Basic unit is meters
// you can use meters, kilometers or miles for this stat
private var distanceStat:Double = 0.0 //private variable so you must use the setters and getters.
public init (){
    self.distanceStat = 0.0

public init(meters:Double){
   self.distanceStat = meters

public init(kilometers:Double){

public init(miles:Double){

// getters distance
public func miles()->Double{
    return distanceStat / 1609.34 

public func meters()->Double{
    return distanceStat

public func kilometers()->Double{
    return distanceStat / 1000.0

public func distance(meters:Double){
    distanceStat = meters

public func distance(miles:Double){
    distanceStat = miles * 1609.34

public func distance(kilometers:Double){
    distanceStat = kilometers * 1000.0


Now to specify a 8K distance, I can say

let newDistance = DistanceStat(kilometers:8.0)

and return that as miles.

print( newDistance.miles())

I do the same with pace and time. With the pace, time, and distance stat in their own classes, I can use them anywhere and get the conversions I need anywhere.  With that I can make summation functions.  I’ll total the distance and the time, and use them to get an average pace for my summation data. That summation data can be in any of the units I have for that type.

I built the model not in the app, but in a separate playground. Playgrounds, especially for models offer an excellent way of looking at all your code and making the debugging process easier.  I can type them in on either my Mac or my iPad and check how every part works, finding errors as I go.  I did for example find an error in my  conversion formulas, and was able to find and fix it from the playground.

In the next installment we’ll add the model to the old Xcode project, get more than a few errors and start hooking up some user interfaces for testing.