输入时在Swift中的文本字段中格式化货币

时间:2022-08-22 11:37:07

I am trying to format currency input in a textfield in Swift as the user inputs it.

我正在尝试在用户输入时在Swift的文本字段中格式化货币输入。

So far, I can only format it successfully when the user finishes inputting:

到目前为止,我只能在用户完成输入时成功格式化:

@IBAction func editingEnded(sender: AnyObject) {

    let formatter = NSNumberFormatter()
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    formatter.locale = NSLocale(localeIdentifier: "en_US")
    var numberFromField = NSString(string: textField.text).doubleValue

    textField.text = formatter.stringFromNumber(numberFromField)
}

However, I would like for the currency to be formatted the moment the user inputs it. When I try to do it on the TextField actions "Editing Changed" or "Value Changed", I can only enter 1 number (if I enter 8, it becomes $8.00) but then once I enter a second number everything goes to $0.00 and I cannot enter further beyond that.

但是,我想在用户输入货币时格式化货币。当我尝试在TextField操作“编辑已更改”或“值已更改”时执行此操作时,我只能输入1个数字(如果我输入8,则变为8.00美元)但是一旦我输入第二个数字,一切都会达到0.00美元而我除此之外不能进一步进入。

Any suggestions? I feel like this should be an easy fix but I can't quite get at it.

有什么建议么?我觉得这应该是一个简单的修复,但我不能完全理解它。

5 个解决方案

#1


19  

I modified the function from earlier today. Works great for "en_US" and "fr_FR". However, for "ja_JP", the division by 100 I do to create decimals is a problem. You will need to have a switch or if/else statement that separates currencies with decimals and those that do not have them when formatted by the formatter. But I think this gets you in the space you wanted to be.

我今天早些时候修改了这个功能。适用于“en_US”和“fr_FR”。但是,对于“ja_JP”,我用100除以创建小数是一个问题。您将需要一个开关或if / else语句,用于将带有小数的货币和那些在格式化器格式化时没有它们的货币分开。但我认为这可以让你进入你想成为的空间。

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!
    var currentString = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self
    }

    //Textfield delegates
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // return NO to not change text

        switch string {
        case "0","1","2","3","4","5","6","7","8","9":
            currentString += string
            println(currentString)
            formatCurrency(string: currentString)
        default:
            var array = Array(string)
            var currentStringArray = Array(currentString)
            if array.count == 0 && currentStringArray.count != 0 {
                currentStringArray.removeLast()
                currentString = ""
                for character in currentStringArray {
                    currentString += String(character)
                }
                formatCurrency(string: currentString)
            }
        }
        return false
    }

    func formatCurrency(#string: String) {
        println("format \(string)")
        let formatter = NSNumberFormatter()
        formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
        formatter.locale = NSLocale(localeIdentifier: "en_US")
        var numberFromField = (NSString(string: currentString).doubleValue)/100
        textField.text = formatter.stringFromNumber(numberFromField)
        println(textField.text )
    }
}

#2


8  

this works for me using NSNumberFormatter...

这适用于我使用NSNumberFormatter ...

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

    // Construct the text that will be in the field if this change is accepted
    var oldText = textField.text as NSString
    var newText = oldText.stringByReplacingCharactersInRange(range, withString: string) as NSString!
    var newTextString = String(newText)

    let digits = NSCharacterSet.decimalDigitCharacterSet()
    var digitText = ""
    for c in newTextString.unicodeScalars {
        if digits.longCharacterIsMember(c.value) {
            digitText.append(c)
        }
    }

    let formatter = NSNumberFormatter()
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    formatter.locale = NSLocale(localeIdentifier: "en_US")
    var numberFromField = (NSString(string: digitText).doubleValue)/100
    newText = formatter.stringFromNumber(numberFromField)

    textField.text = newText

    return false
}

#3


5  

Based on @Robert answer. Updated for Swift 2.0

基于@Robert的回答。针对Swift 2.0进行了更新

//Textfield delegates
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // return NO to not change text

    switch string {
    case "0","1","2","3","4","5","6","7","8","9":
        currentString += string
        formatCurrency(currentString)
    default:
        if string.characters.count == 0 && currentString.characters.count != 0 {
            currentString = String(currentString.characters.dropLast())
            formatCurrency(currentString)
        }
    }
    return false
}

func formatCurrency(string: String) {
    print("format \(string)")
    let formatter = NSNumberFormatter()
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    formatter.locale = NSLocale(localeIdentifier: "en_US")
    let numberFromField = (NSString(string: currentString).doubleValue)/100
    self.amountField.text = formatter.stringFromNumber(numberFromField)
    print(self.amountField.text )
}

#4


3  

For Swift 3.0

对于Swift 3.0

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

        // Construct the text that will be in the field if this change is accepted

        switch string {
        case "0","1","2","3","4","5","6","7","8","9":
            currentString += string
            formatCurrency(currentString)
        default:
            if string.characters.count == 0 && currentString.characters.count != 0 {
                currentString = String(currentString.characters.dropLast())
                formatCurrency(currentString)
            }
        }
        return false    }

    func formatCurrency(_ string: String) {
        print("format \(string)")
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = findLocaleByCurrencyCode("NGN")
        let numberFromField = (NSString(string: currentString).doubleValue)/100
        let temp = formatter.string(from: NSNumber(value: numberFromField))
        self.amountTextField.text = String(describing: temp!.characters.dropFirst())
    }

func findLocaleByCurrencyCode(_ currencyCode: String) -> Locale? {

    let locales = Locale.availableIdentifiers 
    var locale: Locale?     
    for   localeId in locales {     
      locale = Locale(identifier: localeId)     
      if let code = (locale! as NSLocale).object(forKey: NSLocale.Key.currencyCode) as? String { 
        if code == currencyCode {
                return locale       
        }   
    } 
}    
return locale }

#5


1  

I worked out a normal currency format ( eg 1 is as $1.00, 88885 is as $8,8885.00 and 7555.8569 as $7,555.86.

我制定了正常的货币格式(例如1为1.00美元,88885为8,8885.00美元,7555.8569为7,555.86美元。

@IBAction func lostpropertyclicked(sender: AnyObject) {
    var currentString = ""
    currentString = amountTF.text
    formatCurrency(string: currentString)
}

func formatCurrency(#string: String) {
    println("format \(string)")
    let formatter = NSNumberFormatter()
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    formatter.locale = NSLocale(localeIdentifier: "en_US")
    var numberFromField = (NSString(string: currentString).doubleValue)
    currentString = formatter.stringFromNumber(numberFromField)!
    println(currentString )
}

#1


19  

I modified the function from earlier today. Works great for "en_US" and "fr_FR". However, for "ja_JP", the division by 100 I do to create decimals is a problem. You will need to have a switch or if/else statement that separates currencies with decimals and those that do not have them when formatted by the formatter. But I think this gets you in the space you wanted to be.

我今天早些时候修改了这个功能。适用于“en_US”和“fr_FR”。但是,对于“ja_JP”,我用100除以创建小数是一个问题。您将需要一个开关或if / else语句,用于将带有小数的货币和那些在格式化器格式化时没有它们的货币分开。但我认为这可以让你进入你想成为的空间。

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField!
    var currentString = ""

    override func viewDidLoad() {
        super.viewDidLoad()

        self.textField.delegate = self
    }

    //Textfield delegates
    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // return NO to not change text

        switch string {
        case "0","1","2","3","4","5","6","7","8","9":
            currentString += string
            println(currentString)
            formatCurrency(string: currentString)
        default:
            var array = Array(string)
            var currentStringArray = Array(currentString)
            if array.count == 0 && currentStringArray.count != 0 {
                currentStringArray.removeLast()
                currentString = ""
                for character in currentStringArray {
                    currentString += String(character)
                }
                formatCurrency(string: currentString)
            }
        }
        return false
    }

    func formatCurrency(#string: String) {
        println("format \(string)")
        let formatter = NSNumberFormatter()
        formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
        formatter.locale = NSLocale(localeIdentifier: "en_US")
        var numberFromField = (NSString(string: currentString).doubleValue)/100
        textField.text = formatter.stringFromNumber(numberFromField)
        println(textField.text )
    }
}

#2


8  

this works for me using NSNumberFormatter...

这适用于我使用NSNumberFormatter ...

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

    // Construct the text that will be in the field if this change is accepted
    var oldText = textField.text as NSString
    var newText = oldText.stringByReplacingCharactersInRange(range, withString: string) as NSString!
    var newTextString = String(newText)

    let digits = NSCharacterSet.decimalDigitCharacterSet()
    var digitText = ""
    for c in newTextString.unicodeScalars {
        if digits.longCharacterIsMember(c.value) {
            digitText.append(c)
        }
    }

    let formatter = NSNumberFormatter()
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    formatter.locale = NSLocale(localeIdentifier: "en_US")
    var numberFromField = (NSString(string: digitText).doubleValue)/100
    newText = formatter.stringFromNumber(numberFromField)

    textField.text = newText

    return false
}

#3


5  

Based on @Robert answer. Updated for Swift 2.0

基于@Robert的回答。针对Swift 2.0进行了更新

//Textfield delegates
func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { // return NO to not change text

    switch string {
    case "0","1","2","3","4","5","6","7","8","9":
        currentString += string
        formatCurrency(currentString)
    default:
        if string.characters.count == 0 && currentString.characters.count != 0 {
            currentString = String(currentString.characters.dropLast())
            formatCurrency(currentString)
        }
    }
    return false
}

func formatCurrency(string: String) {
    print("format \(string)")
    let formatter = NSNumberFormatter()
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    formatter.locale = NSLocale(localeIdentifier: "en_US")
    let numberFromField = (NSString(string: currentString).doubleValue)/100
    self.amountField.text = formatter.stringFromNumber(numberFromField)
    print(self.amountField.text )
}

#4


3  

For Swift 3.0

对于Swift 3.0

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

        // Construct the text that will be in the field if this change is accepted

        switch string {
        case "0","1","2","3","4","5","6","7","8","9":
            currentString += string
            formatCurrency(currentString)
        default:
            if string.characters.count == 0 && currentString.characters.count != 0 {
                currentString = String(currentString.characters.dropLast())
                formatCurrency(currentString)
            }
        }
        return false    }

    func formatCurrency(_ string: String) {
        print("format \(string)")
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        formatter.locale = findLocaleByCurrencyCode("NGN")
        let numberFromField = (NSString(string: currentString).doubleValue)/100
        let temp = formatter.string(from: NSNumber(value: numberFromField))
        self.amountTextField.text = String(describing: temp!.characters.dropFirst())
    }

func findLocaleByCurrencyCode(_ currencyCode: String) -> Locale? {

    let locales = Locale.availableIdentifiers 
    var locale: Locale?     
    for   localeId in locales {     
      locale = Locale(identifier: localeId)     
      if let code = (locale! as NSLocale).object(forKey: NSLocale.Key.currencyCode) as? String { 
        if code == currencyCode {
                return locale       
        }   
    } 
}    
return locale }

#5


1  

I worked out a normal currency format ( eg 1 is as $1.00, 88885 is as $8,8885.00 and 7555.8569 as $7,555.86.

我制定了正常的货币格式(例如1为1.00美元,88885为8,8885.00美元,7555.8569为7,555.86美元。

@IBAction func lostpropertyclicked(sender: AnyObject) {
    var currentString = ""
    currentString = amountTF.text
    formatCurrency(string: currentString)
}

func formatCurrency(#string: String) {
    println("format \(string)")
    let formatter = NSNumberFormatter()
    formatter.numberStyle = NSNumberFormatterStyle.CurrencyStyle
    formatter.locale = NSLocale(localeIdentifier: "en_US")
    var numberFromField = (NSString(string: currentString).doubleValue)
    currentString = formatter.stringFromNumber(numberFromField)!
    println(currentString )
}