1

I am trying to create a method in swift that takes in a String and returns a Bool. I want to return true if the String is in a correct currency format and false if it is not.

So far this is the method I have tried:

func textIsValidCurrencyFormat(text: String) -> Bool {
    var isValidCurrencyFormat = false

    var numberFormatter = NSNumberFormatter()
    numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    var number = numberFormatter.numberFromString(text)

    if number != nil {
        isValidCurrencyFormat = true
    }

    return isValidCurrencyFormat
}

PROBLEM: This works EXCEPT that I also want to invalidate strings with spaces before or after the amount and if there are more than two numbers after the decimal which this method currently accepts.

Currently I do not care if the method returns true or false based on the currency type (a.k.a. USD or GBP or some other currency) but I may want to use this to reject currencies other than a specific type in the future as well.

EDIT:

This is the final code I have come up with that correctly determines if a string is entered in a correct currency format and accounts for edge cases. Please, add any suggestions in the comments below!

func textIsValidCurrencyFormat(text: String) -> Bool {
    var isValidCurrencyFormat = false

    var numberFormatter = NSNumberFormatter()
    numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    var number = numberFormatter.numberFromString(text)

    if number != nil {
        let numberParts = text.componentsSeparatedByString(".")
        if numberParts.count == 2 {
            let decimalArray = Array(numberParts[1])
            if decimalArray.count <= 2 {
                if text == text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) {
                    isValidCurrencyFormat = true
                }
            }
        } else {
            if text == text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) {
                isValidCurrencyFormat = true
            }
        }

    }

    return isValidCurrencyFormat
}
Reid
  • 734
  • 8
  • 15
  • It would be much easier to manage the input. Take a look at this answer http://stackoverflow.com/a/29783546/2303865 – Leo Dabus May 14 '15 at 19:42

2 Answers2

0

How's this? Return false if precision is greater than cents:

if Double(number!) * 100 != floor(Double(number!) * 100) {
    isValidCurrencyFormat = false
}

And return false if there's whitespace before or after:

if text != text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) {
    isValidCurrencyFormat = false
}

So putting it all together:

func textIsValidCurrencyFormat(text: String) -> Bool {
    var isValidCurrencyFormat = false

    var numberFormatter = NSNumberFormatter()
    numberFormatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    var number = numberFormatter.numberFromString(text)

    if number != nil {
        isValidCurrencyFormat = true
        if Double(number!) * 100 != floor(Double(number!) * 100) {
            isValidCurrencyFormat = false # or just return false here
        }
    }

    if text != text.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet()) {
        isValidCurrencyFormat = false # or just return false here
    }

    return isValidCurrencyFormat
}
leekaiinthesky
  • 5,413
  • 4
  • 28
  • 39
  • One problem with the first if statement's ability to measure precision. It recognizes that $215.001 is not to be accepted but it will still accept $215.000 which should not be accepted. I have figured out a way to do this and will upload my new solution shortly. – Reid May 21 '15 at 15:27
0

I'd definitely take another approach. I'd create a Regex and match it with your currency string, something like this:

func textIsValidCurrencyFormat(text: String) -> Bool {

    if text =~ "^(\$?\d{1,3}(,?\d{3})?(\.\d\d?)?|\(\$?\d{1,3}(,?\d{3})?(\.\d\d?)?\))$" {
        return true
      }

    return false
}

I think the regex works for US$ but I think you can modify it to work with any currency you need.

Boris
  • 11,373
  • 2
  • 33
  • 35