man paying using credit card

100 Days of SwiftUI – Project 1: WeSplit

After 2 weeks of pure Swift we’re finally getting to build an honest-to-goodness iOS app.

Our very first project is a simple app that calculates a tip on a bill (or check, if you’re American) and then splits the total between a number of people. Despite it being relatively straightforward, we’re already making extensive use of everything we’ve learned so far, especially closures!

The thing that strikes me the most while working through the initial build of the app is just how much you get for free when using SwiftUI. You get lovely animated transitions, nice default styles for the controls, different ways of displaying options by changing one modifier…it’s amazing!

Challenge

We wrap up the project with a series of challenges to extend and improve the app.

New header

First, I add a header to the third section:

Section("Amount per person") {
  Text(totalPerPerson, format: .currency(code: Locale.current.currency?.identifier ?? "USD"))
}

Grand total

Next we’ve to add another section showing the grand total before splitting the bill. Here I choose to create a new computed property called grandTotal which does that calculation. I then realised that it repeats almost all the code from the totalPerPerson computed property so I decide to try and rewrite totalPerPerson using the new grandTotal property – Don’t Repeat Yourself!

var grandTotal: Double {
    let tipSelection = Double(tipPercentage)
    
    let tipValue = checkAmount / 100 * tipSelection
    let grandTotal = checkAmount + tipValue
    
    return grandTotal
}

var totalPerPerson: Double {
    grandTotal / Double(numberOfPeople + 2)
}

And then add in the new section showing the grand total.

Section("Check total") {
  Text(grandTotal, format: .currency(code: Locale.current.currency?.identifier ?? "USD"))
}

Percentage picker

The last challenge is to change how the percentage picker works so you can select anything from 0 to 100 on a separate screen. Here I changed what the ForEach loops over to be a number range and changed the pickerStyle to navigationLink.

Picker("Tip percentage", selection: $tipPercentage) {
    ForEach(0..<101) {
        Text($0, format: .percent)
    }
}
.pickerStyle(.navigationLink)

Complete solution

WeSplit on GitHub