Как ввести формат валюты в текстовое поле (справа налево) с помощью Swift?

у меня есть номер, скажем 0.00.

  • когда пользователь нажимает 1. Мы должны были ... --1-->
  • когда пользователь нажимает 2. Мы должны показать 0.12
  • когда пользователь нажимает 3. Мы должны показать 1.23
  • когда пользователь нажимает 4. Мы должны показать 12.34

как я могу сделать это с Swift?

6 ответов


на Swift 3. Введите формат валюты в текстовое поле (справа налево)

override func viewDidLoad() {
    super.viewDidLoad()

    textField.addTarget(self, action: #selector(myTextFieldDidChange), for: .editingChanged)
}

func myTextFieldDidChange(_ textField: UITextField) {

    if let amountString = textField.text?.currencyInputFormatting() {
        textField.text = amountString
    }
}

extension String {

    // formatting text for currency textField
    func currencyInputFormatting() -> String {

        var number: NSNumber!
        let formatter = NumberFormatter()
        formatter.numberStyle = .currencyAccounting
        formatter.currencySymbol = "$"
        formatter.maximumFractionDigits = 2
        formatter.minimumFractionDigits = 2

        var amountWithPrefix = self

        // remove from String: "$", ".", ","
        let regex = try! NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive)
        amountWithPrefix = regex.stringByReplacingMatches(in: amountWithPrefix, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, self.characters.count), withTemplate: "")

        let double = (amountWithPrefix as NSString).doubleValue
        number = NSNumber(value: (double / 100))

        // if first number is 0 or all numbers were deleted
        guard number != 0 as NSNumber else {
            return ""
        }

        return formatter.string(from: number)!
    }
}

вы можете создать текстовое поле валюты подкласса UITextField. Добавьте цель для UIControlEvents .editingChanged. Добавьте метод селектора для фильтрации цифр из строки текстового поля. После фильтрации всех не цифр из вашей строки вы можете снова отформатировать свой номер с помощью NumberFormatter следующим образом:

Swift 4.1 или более поздней версии

class CurrencyField: UITextField {
    var string: String { return text ?? "" }
    var decimal: Decimal {
        return string.digits.decimal /
            Decimal(pow(10, Double(Formatter.currency.maximumFractionDigits)))
    }
    var decimalNumber: NSDecimalNumber { return decimal.number }
    var doubleValue: Double { return decimalNumber.doubleValue }
    var integerValue: Int { return decimalNumber.intValue   }
    let maximum: Decimal = 999_999_999.99
    private var lastValue: String?
    override func willMove(toSuperview newSuperview: UIView?) {
        // you can make it a fixed locale currency if needed
        // Formatter.currency.locale = Locale(identifier: "pt_BR") // or "en_US", "fr_FR", etc
        addTarget(self, action: #selector(editingChanged), for: .editingChanged)
        keyboardType = .numberPad
        textAlignment = .right
        editingChanged()
    }
    override func deleteBackward() {
        text = string.digits.dropLast().string
        editingChanged()
    }
    @objc func editingChanged(_ textField: UITextField? = nil) {
        guard decimal <= maximum else {
            text = lastValue
            return
        }
        text = Formatter.currency.string(for: decimal)
        lastValue = text
    }
}

extension NumberFormatter {
    convenience init(numberStyle: Style) {
        self.init()
        self.numberStyle = numberStyle
    }
}
extension Formatter {
    static let currency = NumberFormatter(numberStyle: .currency)
}
extension String {
    var digits: [UInt8] {
        return map(String.init).compactMap(UInt8.init)
    }
}
extension Collection where Iterator.Element == UInt8 {
    var string: String { return map(String.init).joined() }
    var decimal: Decimal { return Decimal(string: string) ?? 0 }
}
extension Decimal {
    var number: NSDecimalNumber { return NSDecimalNumber(decimal: self) }
}

попробуйте этот фрагмент кода:

struct DotNum {
  private var fraction:String = ""
  private var intval:String = ""
  init() {}
  mutating func enter(s:String) {
    if count(fraction) < 2 {
      fraction = s + fraction
    } else {
      intval = s + intval
    }
  }
  private var sFract:String {
    if count(fraction) == 0 { return "00" }
    if count(fraction) == 1 { return "0\(fraction)" }
    return fraction
  }
  var stringVal:String {
    if intval == ""  { return "0.\(sFract)" }
    return "\(intval).\(sFract)"
  }
}
var val = DotNum()
val.enter("1")
val.stringVal
val.enter("2")
val.stringVal
val.enter("3")
val.stringVal
val.enter("4")
val.stringVal

мой окончательный код, спасибо за помощь

extension Double {
            var twoDigits: Double {
                let nf = NSNumberFormatter()
                nf.numberStyle = NSNumberFormatterStyle.DecimalStyle
                nf.minimumFractionDigits = 2
                nf.maximumFractionDigits = 2
                return self
            }
    }
    var cleanText:String!
            let number:String = sender.currentTitle as String!
            if(amountDisplay.text != nil)
            {
                cleanText = String(Array(amountDisplay.text!).map{String()}.filter{ .toInt() != nil }.map{Character()} ) as String
                cleanText = cleanText + number
            }else{
                cleanText = number
            }

            amount = (Double(cleanText.toInt()!) / 100).twoDigits
            formatter.locale = NSLocale(localeIdentifier: currencies[current_currency_index])
            amountDisplay.text = "\(formatter.stringFromNumber(amount!)!)"

вот код для swift 2

@IBOutlet weak var txtAmount: UITextField!

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

        if string.characters.count == 0 {
            return true
        }

        let userEnteredString = textField.text ?? ""
        var newString = (userEnteredString as NSString).stringByReplacingCharactersInRange(range, withString: string) as NSString
        newString = newString.stringByReplacingOccurrencesOfString(".", withString: "")

        let centAmount : NSInteger = newString.integerValue
        let amount = (Double(centAmount) / 100.0)

        if newString.length < 16 {
            let str = String(format: "%0.2f", arguments: [amount])
            txtAmount.text = str
        }

        return false //return false for exact out put
    }

Примечание: подключите делегат для textField из раскадровки или программно


просто для удовольствия: скопировал Томас (полные кредиты-и очки-ему пожалуйста) в файл для запуска в виде сценария Swift 4.1 (с незначительными исправлениями):

dotnum.Свифт:

#!/usr/bin/swift

struct DotNum {
    private var fraction:String = ""
    private var intval:String = ""
    init() {}
    mutating func enter(_ s:String) {
        if fraction.count < 2 {
          fraction = s + fraction
        } else {
          intval = s + intval
        }
    }
    private var sFract:String {
        if fraction.count == 0 { return "00" }
        if fraction.count == 1 { return "0\(fraction)" }
        return fraction
    }
    var stringVal:String {
        if intval == ""  { return "0.\(sFract)" }
        return "\(intval).\(sFract)"
    }
}

var val = DotNum()
val.enter("1")
print(val.stringVal)
val.enter("2")
print(val.stringVal)
val.enter("3")
print(val.stringVal)
val.enter("4")
print(val.stringVal)

затем запустите его в терминале:

$ chmod +x dotnum.swift
$ ./dotnum.swift
0.01
0.21
3.21
43.21