Bloco numérico do UITextField: ponto em vez de vírgula para valores flutuantes

Estou usando um textField que é preenchido de um bloco numérico.

O problema é que, com muitos formatos de região local (todos europeus, por exemplo), o bloco numérico do UITextField tem vírgula em vez de ponto, então toda vez que escrevo um número decimal, o UITextField não reconhece a vírgula decimal e o número redondo; por exemplo, 23,07 se tornam 23.

Como posso resolver isso? Eu pensei em definir o textField fixo nos EUA; é possível? Como?

Eu li o valor usando isso:

var importo = (importoPrevistoTF.text as NSString).floatValue 

Potencial duplicado da Resposta SO , use NSNumberFormatter

Exemplo Swift:

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

Exemplo (objective-C):

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

Isso já foi perguntado e respondido aqui . Você pode fazê-lo funcionar com vírgula e ponto como segue:

atualização: Swift 3.0.2 • Xcode 8.2.1

 extension String { var floatValue: Float { let nf = NumberFormatter() nf.decimalSeparator = "." if let result = nf.number(from: self) { return result.floatValue } else { nf.decimalSeparator = "," if let result = nf.number(from: self) { return result.floatValue } } return 0 } } 

Swift 2

 extension String { var floatValue: Float { let nf = NSNumberFormatter() nf.decimalSeparator = "." if let result = nf.numberFromString(self) { return result.floatValue } else { nf.decimalSeparator = "," if let result = nf.numberFromString(self) { return result.floatValue } } return 0 } } "23.07".floatValue // 23.07 "23,07".floatValue // 23.07 

Ninguém realmente abordou a questão diretamente.

Ou seja, o separador decimal é uma convenção para uma localidade.

O iOS suporta números de formatação baseados em uma localidade específica.

Se você está trabalhando puramente em uma determinada localidade, então tudo deve funcionar corretamente. O teclado deve aceitar números com o separador decimal correto.

Se você estiver na maioria dos países da Europa, por exemplo, você inserirá uma vírgula como separador decimal. Inserir um ponto nesses países está errado. Alguém de um desses países não faria isso, porque é o separador decimal errado. Um usuário europeu vai saber usar uma vírgula como separador decimal e você não precisa fazer nada.

Se você estiver nos EUA, você usaria um período. Usar uma vírgula nos EUA seria errado.

A maneira como você deve exibir um número decimal é com um formatador numérico. Quando você cria um formatador numérico, ele usa a localidade atual por padrão.

Se você precisar converter uma string contendo um número decimal de uma localidade para outra, deverá usar 2 formatadores numéricos. Use um formatador no código do idioma de origem para converter a sequência em float. Em seguida, use um formatador com a localidade de destino para converter o número em uma string no formato de saída.

Basta criar um formatador numérico na localidade atual padrão e criar um segundo formatador numérico e definir sua localidade explicitamente para a outra localidade que você deseja usar.

Provavelmente é uma duplicata dessa resposta , mas como o original está em Objective-C, aqui está uma versão do Swift:

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

Como o NSNumberFormatter foi substituído pelo NumberFormatter na versão recente do Swift, tenho o prazer de compartilhar com você uma solução possível atualizada:

 var numberFormatter: NumberFormatter() importo = Float(numberFormatter.number(from: importoPrevistoTF.text!)!) 

Swift 3: float ou double value para string contendo ponto flutuante com vírgula

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

Exemplo:

 "5,456".floatValue //5.456 "5.456".floatValue //5.456 "5,456".doubleValue //5.456 "5.456".doubleValue //5.456 "5,456".doubleValue.rounded() //5 "5,6".doubleValue.rounded() //6 

Uma solução que encontrei:

 let nf = NumberFormatter() nf.locale = Locale.current let numberLocalized = nf.number(from: txtAlcool.text!) 

No meu caso eu estava testando no xcode e tudo deu certo, mas ao testar no dispositivo ele estava travando. Tudo porque no Brasil usamos sistema métrico, decimal separado por vírgula “,”. Com esta solução, converte automaticamente de vírgula para ponto.

  let number = NSNumberFormatter() let locale = NSLocale.currentLocale() let decimalCode = locale.objectForKey(NSLocaleDecimalSeparator) as! NSString number.decimalSeparator = decimalCode as String let result = number.numberFromString(textField.text!) let value = NSNumberFormatter.localizedStringFromNumber(result!.floatValue, numberStyle: .DecimalStyle) print(value) 

Espero que isso ajude você 🙂

Solução Swift 4, sem usar preferredLanguages ​​eu tive problemas com fr_US e decimalPad

 extension String { func number(style: NumberFormatter.Style = .decimal) -> NSNumber? { return [[Locale.current], Locale.preferredLanguages.map { Locale(identifier: $0) }] .flatMap { $0 } .map { locale -> NSNumber? in let formatter = NumberFormatter() formatter.numberStyle = style formatter.locale = locale return formatter.number(from: self) }.filter { $0 != nil } .map { $0! } .first } } textfield.text?.number()?.floatValue 

Você pode convertê-lo usando NumberFormatter e filtrando os diferentes separadores decimais:

 func getDoubleFromLocalNumber(input: String) -> Double { var value = 0.0 let numberFormatter = NumberFormatter() let decimalFiltered = input.replacingOccurrences(of: "٫|,", with: ".", options: .regularExpression) numberFormatter.locale = Locale(identifier: "EN") if let amountValue = numberFormatter.number(from: decimalFiltered) { value = amountValue.doubleValue } return value }