UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

SOLVED: Day 18 - WeSplit - Amount Per Person Displays "$-NaN"

Forums > 100 Days of SwiftUI

Hi there,

As part of the Day 18 wrap-up challenge, I changed the Number of People field from a Picker to a Text Field. After doing so, the Amount Per Person displays "$-NaN" until you enter values for the Check Amount and Number of People fields.

I'm handling that Number of People text field in the same way as the Check Amount field by converting the String to a Double. But for some reason I'm getting a different result.

Has anyone run into this before or can spot what I'm doing wrong?

Many thanks! Patrick

Screen recording of the issue

import SwiftUI

struct ContentView: View {

    @State private var checkAmount = ""
    @State private var numberOfPeople = ""
    @State private var tipPercentage = 2

    let tipPercentages = [10, 15, 20, 25, 0]

    var checkTotal: Double {
        let orderAmount = Double(checkAmount) ?? 0
        let tipSelection = Double(tipPercentages[tipPercentage])

        let tipValue = orderAmount / 100 * tipSelection
        let totalWithTip = orderAmount + tipValue

        return totalWithTip
    }

    var totalPerPerson: Double {
        let peopleCount = Double(numberOfPeople) ?? 0
        let tipSelection = Double(tipPercentages[tipPercentage])
        let orderAmount = Double(checkAmount) ?? 0

        let tipValue = orderAmount / 100 * tipSelection
        let grandTotal = orderAmount + tipValue
        let amountPerPerson = grandTotal / peopleCount

        return amountPerPerson
    }

    var body: some View {
        NavigationView {
            Form {
                Section {
                    TextField("Enter Check Amount", text: $checkAmount)
                        .keyboardType(/*@START_MENU_TOKEN@*/.decimalPad/*@END_MENU_TOKEN@*/)
                    TextField("Enter Number of People", text: $numberOfPeople)
                    .keyboardType(/*@START_MENU_TOKEN@*/.decimalPad/*@END_MENU_TOKEN@*/)

                }

                Section(header: Text("How much tip do you want to leave?")) {
                    Picker("Tip Percentage", selection: $tipPercentage) {
                        ForEach(0 ..< tipPercentages.count) {
                            Text("\(self.tipPercentages[$0])%")
                        }
                    }
                    .pickerStyle(SegmentedPickerStyle())
                }

                Section(header: Text("Check Total")) {
                    Text("$\(checkTotal, specifier: "%.2f")")
                }

                Section(header: Text("Amount Per Person")) {
                    Text("$\(totalPerPerson, specifier: "%.2f")")
                }
            }
            .navigationBarTitle("WeSplit")
        }
    }
}

3      

Hello Patrick,

I'm new to SwiftUI (and Swift!) but I think I know what's happened.

NaN is code speak for "Not a Number" and often means that an illegal numerical operation has occurred - often divide by 0, which in effect results in a value of Infinity! NaN.

The initial value of your numberOfPeople is "", which means that as SwiftUI resolves all @State values for the View at start will set peopleCount to 0. It will then calculate totalPerPerson which contains:

let amountPerPerson = grandTotal / peopleCount

which is a divide by 0 which results in Infinity - NaN.

In Paul's code, numberOfPeople is initialised to "2" which avoids this issue. There is also the computed value 'numPeople' which addresses this issue, but that isn't used in the per person calculations. I haven't tried, but I expect that the original code would produce the error you are getting if you deliberately set the number of people to 0.

I hope that helps.

Stephen

3      

@BlackTablet is right. You should default peopleCount to 1 or 2 instead of 0 when the conversion to Double fails.

let peopleCount = Double(numberOfPeople) ?? 1

4      

Thanks so much @BlackTablet and @guseulalio. That makes sense.

3      

BUILD THE ULTIMATE PORTFOLIO APP Most Swift tutorials help you solve one specific problem, but in my Ultimate Portfolio App series I show you how to get all the best practices into a single app: architecture, testing, performance, accessibility, localization, project organization, and so much more, all while building a SwiftUI app that works on iOS, macOS and watchOS.

Get it on Hacking with Swift+

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.