UITextField's numerical pad: dot instead of comma for float values

Solution 1:

Swift 4

extension String {
    static let numberFormatter = NumberFormatter()
    var doubleValue: Double {
        String.numberFormatter.decimalSeparator = "."
        if let result =  String.numberFormatter.number(from: self) {
            return result.doubleValue
        } else {
            String.numberFormatter.decimalSeparator = ","
            if let result = String.numberFormatter.number(from: self) {
                return result.doubleValue
            }
        }
        return 0
    }
}

"2.25".doubleValue // 2.25
"2,25".doubleValue // 2.25


Localized approach using NumberFormatter:

extension NumberFormatter {
    static let shared = NumberFormatter()
}
extension StringProtocol {
    var doubleValue: Double? {
        return NumberFormatter.shared.number(from: String(self))?.doubleValue
    }
}

Playground testing

// User device's default settings for current locale (en_US)
NumberFormatter.shared.locale            // en_US (current)
NumberFormatter.shared.numberStyle       // none
NumberFormatter.shared.decimalSeparator  // "."
"2.7".doubleValue  // 2.7
"2,7".doubleValue  // nil
"$2.70".doubleValue  // nil

NumberFormatter.shared.numberStyle  = .currency
"2.7".doubleValue  // nil
"2,7".doubleValue  // nil
"$2.70".doubleValue  // 2.7


NumberFormatter.shared.locale  = Locale(identifier: "pt_BR") // pt_BR (fixed)
"2.7".doubleValue     // nil
"2,7".doubleValue     // nil
"R$2,70".doubleValue  // 2.7

NumberFormatter.shared.numberStyle = .none
"2.7".doubleValue      // nil
"2,7".doubleValue      // 2.7
"R$2,70".doubleValue   // nil

Solution 2:

Potential duplicate of the SO Answer, use NSNumberFormatter

Example Swift:

let number = NSNumberFormatter().numberFromString(numberString)
if let number = number {
    let floatValue = Float(number)
}

Example (Objective-C):

NSNumber *number = [[NSNumberFormatter new] numberFromString: numberString];
float floatValue = number.floatValue;

Solution 3:

Nobody has really addressed the issue directly.

That is, the decimal separator is a convention for a locale.

iOS supports formatting numbers based on a particular locale.

If you're working purely in a given locale, then everything should work correctly. The keypad should accept numbers with the correct decimal separator.

If you're in most countries in Europe, for example, you'd enter a comma as the decimal separator. Entering a dot in those countries is wrong. Somebody from one of those countries would not do that, because it is the wrong decimal separator. A European user is going to know to use a comma as the decimal separator and you don't have to do anything.

If you are in the US, you'd use a period. Using a comma in the US would be wrong.

The way you should display a decimal number is with a number formatter. When you create a number formatter, it uses the current locale by default.

If you need to convert a string containing a decimal number from one locale to the other, you should use 2 number formatters. Use a formatter in the source locale to convert the string to a float. Then use a formatter with the destination locale to convert the number to a string in the output format.

Simply create one number formatter in the default current locale, and create a second number formatter and set it's locale explicitly to the other locale that you want to use.

Solution 4:

It's probably a duplicate of this answer, but since the original is in Objective-C, here's a Swift version:

let label = "23,07"
let formatter = NSNumberFormatter()
let maybeNumber = formatter.numberFromString(label)
if let number = maybeNumber {
    println(number)   // 23.07
}