Can't get UITextField to populate when using .

2019-08-25 06:11发布

I borrowed and modified some code from SO to solve a problem where I was trying to format text that I inputted into my UITextFields. If I use the .decimal numberStyle of NumberFormatter it works (adds a comma where I need it) but if I use .currency I can't type anything once I run the app. The UITextField will not populate.

I've tried playing around with the locale and that doesn't seem to solve anything.

All I want to do is to show the user the "$" sign in front of the number they type as soon as they start typing into the UITextField

It's doing it with or without the digitsOnly extension I'm using, so that doesn't seem to be causing it.

Relevant code:

case annualBill!:
    if isNumeric {
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.currencySymbol = "$"

        let newString = (textField.text! as NSString).replacingCharacters(in: range, with: string)
        let numberWithOutCommas = newString.replacingOccurrences(of: ",", with: "")
        let number = formatter.number(from: numberWithOutCommas)
        if number != nil {
            let formattedString = formatter.string(from: number!)
            textField.text = formattedString
            values.annualBill = Decimal(string: (textField.text?.digitsOnly)!)
            print(values.annualBill ?? "NA")
        } else {
            textField.text = nil
        }

extension String {
    var digitsOnly: String {
        return components(separatedBy: 
    NSCharacterSet.decimalDigits.inverted).joined(separator: "")
        }
    }

2条回答
SAY GOODBYE
2楼-- · 2019-08-25 06:37

Try this in your text field delegate.

var amountString = ""

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if !string.isValidCharacterForCurrency() {
        return false
    }

    let formatter = NumberFormatter()
    formatter.minimumFractionDigits = 2
    formatter.maximumFractionDigits = 2

    if string.count > 0 {
        amountString += string
        let decNumber = NSDecimalNumber(string: amountString).multiplying(by: 0.01)
        let newString = "$" + formatter.string(from: decNumber)!
        textField.text = newString

    }
    else {

        amountString = String(amountString.dropLast())
        if amountString.count > 0 {
            let decNumber = NSDecimalNumber(string: amountString).multiplying(by: 0.01)
            let newString = "$" +  formatter.string(from: decNumber)!
            textField.text = newString
        }
        else {
            textField.text = "$0.00"
        }
    }
    return false
}
extension String {

    func isValidCharacterForCurrency() -> Bool {

        let intValue = Int(self)
        return !(intValue == 0 && self != "0" && self != "")
    }
}
查看更多
够拽才男人
3楼-- · 2019-08-25 06:53

Try this code in your extension and use it with your newString and currencyCode such as USD, best is to use with the number with decimal keyboard so you wont need to check the format beforehand

public func toCurrencyFormatter(with currencyCode: String) -> String {
        if NSDecimalNumber(string: self) != NSDecimalNumber.notANumber {
            let formatter = NumberFormatter()
            formatter.numberStyle = .currency
            formatter.currencyCode = currencyCode
            guard let formattedStr = formatter.string(from: NSDecimalNumber(string: self)) else { return self }
            return formattedStr
        }
        return self
    }
查看更多
登录 后发表回答