How to Use Swift Computed Properties to Create a Simple Goal Tracker Class

This is the fourth Swift tutorial and video in a series I’m doing on Swift development.

Source code examples are available on GitHub

In this tutorial, we’re going to take a look at Swift computed properties and how they work. We’re going to create a very simple GoalTracker class. All our GoalTracker class is going to do is track our progress through something, i.e. how many miles or kilometers we’ve run, or how many pages we’ve read in a book, etc. but we’re going to keep it pretty simple.

Setup GoalTracker Swift Class

First, let’s create a class called GoalTracker.

class GoalTracker {
}

Next, on our GoalTracker class, we’re going to create a variable property called goal and give it a type of Double and we’re going to initialize it to zero.

class GoalTracker {
  var goal: Double = 0.0
}

Next, we’re going to create another variable property. Let’s call it unitsCompleted. It’s also going to be a Double and we’ll also initialize it to zero.

class GoalTracker {
  var goal: Double = 0.0
  var unitsCompleted: Double = 0.0
}

##Swift Read-only computed properties
Finally, let’s create another variable property called unitsLeft and it will be a Double but instead of initializing it to zero, we’re going to use curly braces and declare this as a read-only computed property. Now, the way read-only computed properties work, all we have to do is return an instance of a double type. In this case, to determine units left, all we need to do is return the goal minus the units completed.

class GoalTracker {
  var goal: Double = 0.0
  var unitsCompleted: Double = 0.0
  var unitsLeft: Double {
    return goal - unitsCompleted
  }
}

That’s it. We can check this by declaring a variable called goalTracker and then we’ll just initialize a GoalTracker. We can then set the goal property of the goalTracker variable. In this case, we’ll set it to 20.0.

var goalTracker = GoalTracker()
goalTracker.goal = 20.0

Now, if we now take our GoalTracker and we set our units completed property to 5.0 and then we can print our GoalTracker unitsLeft property.

goalTracker.unitsCompleted = 5.0
println(goalTracker.unitsLeft) //15.0

Great, it works! What if we wanted to set unitsLeft and determine our unitsCompleted? Well, we can do that by reformatting the unitsLeft computed property.

Swift Getter and Setter

First, we’re going to declare a getter function on the computed property. Every computed property in swift can have a getter and a setter. We can create a getter by simply wrapping our original expression in a “get” function.

class GoalTracker {
  var goal: Double = 0.0
  var unitsCompleted: Double = 0.0
  var unitsLeft: Double {
    get {
      return goal - unitsCompleted
    }
  }
}

We’ll declare the setter which takes a parameter called “newUnitsLeft”. This parameter is provided automatically when we declare a setter in a Swift computed property. All it does is prepend a “new”” to the front of whatever property we’ve declared. In this case, it’s just newUnitsLeft. Given newUnitsLeft, we can determine the unitsCompleted. We simply set unitsCompleted equal to the goal minus the newUnitsLeft parameter. That’s it.

class GoalTracker {
  var goal: Double = 0.0
  var unitsCompleted: Double = 0.0
  var unitsLeft: Double {
    get {
      return goal - unitsCompleted
    }

    set(newUnitsLeft){
      unitsCompleted = goal - newUnitsLeft
    }
  }
}

Now, if we change unitsCompleted to unitsLeft and then we get our units completed, you can see that we can now determine our units completed from our units left if we change that to 8.3, now you can see that unitsCompleted is updated to 11.7.

goalTracker.unitsLeft = 8.3
println(goalTracker.unitsCompleted) //11.7

Percentage Completed

But let’s say we wanted to take this one step further and we wanted to find out how much we’ve completed as a percentage, how would we do that? We can do that by declaring another computed property on our GoalTracker class. Let’s declare a variable property called percentageCompleted. This is going to be a double and a computed property.

class GoalTracker {
  var goal: Double = 0.0
  var unitsCompleted: Double = 0.0

  var percentageCompleted: Double {
  }

  var unitsLeft: Double {
    get {
      return goal - unitsCompleted
    }

    set(newUnitsLeft){
      unitsCompleted = goal - newUnitsLeft
    }
  }
}

We’re going to use a getter and a setter. In this case, we’ll declare the getter first. To determine the percentage completed, all we need to do is return the unitsCompleted divided by the goal. We’ll also want to format our percentageCompleted because both dividing goals and unitsCompleted will result in a decimal, so if we do multiply it by 100, we’ll get a percentage.

class GoalTracker {
  var goal: Double = 0.0
  var unitsCompleted: Double = 0.0

  var percentageCompleted: Double {
    get {
      return unitsCompleted/goal * 100
    }
  }

  var unitsLeft: Double {
    get {
      return goal - unitsCompleted
    }

    set(newUnitsLeft){
      unitsCompleted = goal - newUnitsLeft
    }
  }
}

In the setter, we’re going to pass in the new percentageCompletedParameter that’s provided by Swift and then set unitsCompleted equal to the goal times the newPercentageCompleted divided by 100. This will allow us to input the percentage completed as a whole number instead of having to input it as a decimal.

class GoalTracker {
  var goal: Double = 0.0
  var unitsCompleted: Double = 0.0

  var percentageCompleted: Double {
    get {
      return unitsCompleted/goal * 100
    }

    set(newPercentageCompleted){
      unitsCompleted = goal * (newPercentageCompleted/100)
    }
  }

  var unitsLeft: Double {
    get {
      return goal - unitsCompleted
    }

    set(newUnitsLeft){
      unitsCompleted = goal - newUnitsLeft
    }
  }
}

Now, we can test it out. If we set 8.3 as our unitsLeft, then our percentageCompleted is 58.5%. If we wanted to see percentageCompleted if we pass in 10.0 for our units completed, the percentage is 50%. We can also change this to say, 1.2 and the percentageCompleted is 6%. Our percentage completed is working as intended.

goalTracker.unitsLeft = 8.3
println(goalTracker.percentageCompleted) //58.5
goalTracker.unitsCompleted = 10.0
println(goalTracker.percentageCompleted) //50.0
goalTracker.unitsCompleted = 1.2
println(goalTracker.percentageCompleted) //6.0

If we wanted to check our setter, we just take our percentage completed property and we set it equal to 2.46% and then the units left would be 17.54.

goalTracker.percentageCompleted = 2.46
println(goalTracker.unitsLeft) //17.54

Adam DeLong - Freelance Ruby on Rails Developer Hey, I’m Adam. I’m guessing you just read this post from somewhere on the interwebs. Hope you enjoyed it.

You can also follow me on the Twitters at: @DeLongShot