Search code examples
swiftcore-datacurrency

Saving decimal and currency in Core Data


Is it possible to save numbers with grouping separators and currency into core data and if so can someone point me in the right direction.

I have mile.text which is a decimal number with the grouping separator, payPerMile.text which is currency and then the grossPay.text which is also currency.

Everything calculates and displays fine until I save it. I print the numbers when I save, everything after the grouping separator is gone and the currency lines display as NaN.

@IBAction func save(_ sender: UIButton) {

    if let item = item {

        item.startdate = startDate.text
        item.unitnumber = unitNumber.text
        item.miles = NSDecimalNumber(string: miles.text ?? "0.0")
        item.paypermile = NSDecimalNumber(string: payPerMile.text ?? "0.00")
        item.grosspay = NSDecimalNumber(string: grossPay.text ?? "0.00")
        item.company = company.text
        item.destination = destination.text
        item.enddate = endDate.text

    } else if let entitydescription = NSEntityDescription.entity(forEntityName: "DriveAwayMain", in: pc) {

        let item = DriveAwayMain(entity: entitydescription, insertInto: pc)

        item.startdate = startDate.text
        item.unitnumber = unitNumber.text
        item.miles = NSDecimalNumber(string: miles.text ?? "0.0")
        item.paypermile = NSDecimalNumber(string: payPerMile.text ?? "0.00")
        item.grosspay = NSDecimalNumber(string: grossPay.text ?? "0.00")
        item.company = company.text
        item.destination = destination.text
        item.enddate = endDate.text

    }

Solution

  • NSDecimalNumber(string:) only accepts plain numbers, not formatted numbers. If the user is entering formatted currency values then you need to use a NumberFormatter in .currency mode to parse the string into a number.

    Example:

    print(NSDecimalNumber(string: "$4,560.45"))
    

    Output:

    NaN

    Using a NumberFormatter:

    let curFmt = NumberFormatter()
    curFmt.generatesDecimalNumbers = true
    curFmt.numberStyle = .currency
    if let num = curFmt.number(from: "$4,560.45") {
        print(num)
    } else {
        print("Not valid currency number")
    }
    

    Output:

    4560.45