Converter String para flutuar no Swift da Apple

Eu estou tentando converter números tirados de um UITextField, que eu presumo, são realmente seqüências de caracteres e convertê-los para flutuar, para que eu possa multiplicá-los.

Eu tenho dois UITextfield s que são declarados da seguinte forma:

 @IBOutlet var wage: UITextField @IBOutlet var hour: UITextField 

Quando o usuário pressiona um UIButton, eu quero calcular os salários que o usuário ganha, mas não posso, já que preciso convertê-los em carros alegóricos primeiro, antes de poder usá-los.

Eu sei como convertê-los em um inteiro fazendo isso:

 var wageConversion:Int = 0 wageConversion = wage.text.toInt()! 

No entanto, não tenho idéia de como convertê-los em carros alegóricos.

Swift 2.0+

Agora, com o Swift 2.0, você pode simplesmente usar o Float(Wage.text) que retorna um Float? tipo. Mais claro que a solução abaixo que apenas retorna 0 .

Se você quiser um valor 0 para um Float inválido, por algum motivo, você pode usar Float(Wage.text) ?? 0 Float(Wage.text) ?? 0 que retornará 0 se não for um Float válido.


Solução antiga

A melhor maneira de lidar com isso é a transmissão direta:

 var WageConversion = (Wage.text as NSString).floatValue 

Na verdade, criei uma extension para usar melhor isso também:

 extension String { var floatValue: Float { return (self as NSString).floatValue } } 

Agora você pode simplesmente chamar var WageConversion = Wage.text.floatValue e permitir que a extensão manipule a ponte para você!

Esta é uma boa implementação, pois pode lidar com flutuações reais (input com . ) E também ajudará a impedir que o usuário copie texto para seu campo de input ( 12p.34 , ou mesmo 12.12.41 ).

Obviamente, se a Apple adicionar um floatValue ao Swift, isso lançará uma exceção, mas pode ser bom nesse meio tempo. Se eles adicionarem mais tarde, tudo o que você precisa fazer para modificar seu código é remover a extensão e tudo funcionará perfeitamente, já que você já estará chamando .floatValue !

Além disso, variables ​​e constantes devem começar com letras minúsculas (incluindo IBOutlets )

Porque em algumas partes do mundo, por exemplo, uma vírgula é usada em vez de um decimal. É melhor criar um NSNumberFormatter para converter uma string em float.

 let numberFormatter = NSNumberFormatter() numberFormatter.numberStyle = NSNumberFormatterStyle.DecimalStyle let number = numberFormatter.numberFromString(self.stringByTrimmingCharactersInSet(Wage.text)) 

Eu converto String para Float dessa maneira:

 let numberFormatter = NSNumberFormatter() let number = numberFormatter.numberFromString("15.5") let numberFloatValue = number.floatValue println("number is \(numberFloatValue)") // prints "number is 15.5" 

Atualizar

A resposta aceita mostra uma maneira mais atualizada de fazer

Swift 1

É assim que Paul Hegarty mostrou na class CS193p de Stanford em 2015:

 wageConversion = NSNumberFormatter().numberFromString(wage.text!)!.floatValue 

Você pode até criar uma propriedade computada para não ter que fazer isso toda vez

 var wageValue: Float { get { return NSNumberFormatter().numberFromString(wage.text!)!.floatValue } set { wage.text = "\(newValue)" } } 

Usando a solução aceita, eu estava achando que o meu “1.1” (quando usando a conversão. FloatValue) seria convertido para 1.10000002384186, que não era o que eu queria. No entanto, se eu usasse o .doubleValue, obteria o 1.1 que queria.

Por exemplo, em vez de usar a solução aceita, usei isso:

 var WageConversion = (Wage.text as NSString).doubleValue 

No meu caso, não precisei de precisão dupla, mas usar o .floatValue não estava me dando o resultado adequado.

Só queria acrescentar isso à discussão no caso de alguém ter se deparado com o mesmo problema.

Abaixo, você terá um Float opcional, coloque um! no final, se você sabe que é um Float, ou use se / let.

 let wageConversion = Float(wage.text) 
 import Foundation "-23.67".floatValue // => -23.67 let s = "-23.67" as NSString s.floatValue // => -23.67 

Aqui está uma adaptação do Swift 3 da solução de Paul Hegarty da resposta do rdprado, com alguma verificação de opções adicionadas a ele (retornando 0.0 se alguma parte do processo falhar):

 var wageFloat:Float = 0.0 if let wageText = wage.text { if let wageNumber = NumberFormatter().number(from: wageText) { wageFloat = wageNumber.floatValue } } 

A propósito, peguei a class CS193p de Stanford usando a iTunes University quando ela ainda estava ensinando Objective-C.

Eu encontrei Paul Hegarty para ser um instrutor fantástico, e eu recomendo a class para qualquer um começando como um desenvolvedor iOS no Swift !!!

 extension String { func floatValue() -> Float? { if let floatval = Float(self) { return floatval } return nil } } 

Você tem duas opções que são bastante semelhantes (pela abordagem e resultado):

 // option 1: var string_1 : String = "100" var double_1 : Double = (string_1 as NSString).doubleValue + 99.0 // option 2: var string_2 : NSString = "100" // or: var string_2 = "100" as NSString var number_2 : Double = string_2.doubleValue; 

Double() constrói um Double a partir de um Int, assim:

var convertedDouble = Double(someInt)

Observe que isso só funcionará se o seu texto realmente contiver um número. Como o Wage é um campo de texto, o usuário pode inserir o que quiser e isso triggersrá um erro de tempo de execução quando você for desencheckboxr o Opcional retornado de toInt() . Você deve verificar se a conversão foi bem-sucedida antes de forçar o unboxing.

 if let wageInt = Wage.text?.toInt() { //we made it in the if so the conversion succeeded. var wageConversionDouble = Double(wageInt) } 

Editar:

Se você tiver certeza de que o texto será um número inteiro, você pode fazer algo assim (observe que o text no UITextField também é Opcional)):

 if let wageText = Wage.text { var wageFloat = Double(wageText.toInt()!) } 

Foi assim que me aproximei. Eu não queria “atravessar a ponte”, como foi removido do Xcode 6 beta 5 de qualquer maneira, rápido e sujo:

 extension String { // converting a string to double func toDouble() -> Double? { // split the string into components var comps = self.componentsSeparatedByString(".") // we have nothing if comps.count == 0 { return nil } // if there is more than one decimal else if comps.count > 2 { return nil } else if comps[0] == "" || comps[1] == "" { return nil } // grab the whole portion var whole = 0.0 // ensure we have a number for the whole if let w = comps[0].toInt() { whole = Double(w) } else { return nil } // we only got the whole if comps.count == 1 { return whole } // grab the fractional var fractional = 0.0 // ensure we have a number for the fractional if let f = comps[1].toInt() { // use number of digits to get the power var toThePower = Double(countElements(comps[1])) // compute the fractional portion fractional = Double(f) / pow(10.0, toThePower) } else { return nil } // return the result return whole + fractional } // converting a string to float func toFloat() -> Float? { if let val = self.toDouble() { return Float(val) } else { return nil } } } // test it out var str = "78.001" if let val = str.toFloat() { println("Str in float: \(val)") } else { println("Unable to convert Str to float") } // now in double if let val = str.toDouble() { println("Str in double: \(val)") } else { println("Unable to convert Str to double") } 

Por uma questão de integridade, esta é uma solução que usa uma extensão do UITextField que também pode considerar uma localidade diferente.

Para o Swift 3+

 extension UITextField { func floatValue(locale : Locale = Locale.current) -> Float { let numberFormatter = NumberFormatter() numberFormatter.numberStyle = .decimal numberFormatter.locale = locale let nsNumber = numberFormatter.number(from: text!) return nsNumber == nil ? 0.0 : nsNumber!.floatValue } } 

Usa isto:

  // get the values from text boxes let a:Double = firstText.text.bridgeToObjectiveC().doubleValue let b:Double = secondText.text.bridgeToObjectiveC().doubleValue // we checking against 0.0, because above function return 0.0 if it gets failed to convert if (a != 0.0) && (b != 0.0) { var ans = a + b answerLabel.text = "Answer is \(ans)" } else { answerLabel.text = "Input values are not numberic" } 

Jeito fácil:

 // toInt returns optional that's why we used a:Int? let a:Int? = firstText.text.toInt() let b:Int? = secondText.text.toInt() // check a and b before unwrapping using ! if a && b { var ans = a! + b! answerLabel.text = "Answer is \(ans)" } else { answerLabel.text = "Input values are not numberic" } 

você pode usar a mesma abordagem para outros cálculos, espero que essa ajuda !!