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

声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow 原文地址: http://stackoverflow.com/questions/26569144/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me): StackOverFlow

提示:将鼠标放在中文语句上可以显示对应的英文。显示中英文
时间:2020-08-31 03:21:22  来源:igfitidea点击:

Format currency in textfield in Swift on input

iosobjective-cswift

提问by zavtra

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.

有什么建议?我觉得这应该是一个简单的解决方法,但我不太明白。

回答by Steve Rosenberg

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 是一个问题。您将需要有一个 switch 或 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 )
    }
}

回答by Yuttanant Suwansiri

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
}

回答by fahrulazmi

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 )
}

回答by Ajay Singh Mehra

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 }

回答by A.G

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 )
}

回答by iAmericanBoy

This worked for me: Naming of the variables need to be improved though. Multiplying by 10 was easy but figuring out how to divide by 10 and round down was tricky with the pointers.

这对我有用:尽管需要改进变量的命名。乘以 10 很容易,但弄清楚如何除以 10 并向下取整对于指针来说很棘手。

    let numberFormatter = NumberFormatter()
    numberFormatter.numberStyle = .currency


    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    if textField == amountTextField {
        guard let text = textField.text else {return true}

        let oldDigits = numberFormatter.number(from: text) ?? 0
        var digits = oldDigits.decimalValue

        if let digit = Decimal(string: string) {
            let newDigits: Decimal = digit / 100

            digits *= 10
            digits += newDigits
        }
        if range.length == 1 {
            digits /= 10
            var result = Decimal(integerLiteral: 0)
            NSDecimalRound(&result, &digits, 2, Decimal.RoundingMode.down)
            digits = result
        }

        textField.text = NumberFormatter.localizedString(from: digits as NSDecimalNumber, number: .currency)
        return false
    } else {
        return true
    }
}