Подтвердить что ты не робот

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

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

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

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

4b9b3361

Ответ 1

Для 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)!
    }
}

Ответ 2

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

Swift 5 или позже

class CurrencyField: UITextField {
    var string: String { return text ?? "" }
    var decimal: Decimal {
        return string.decimal /
            pow(10, 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() {
        guard decimal <= maximum else {
            text = lastValue
            return
        }
        text = Formatter.currency.string(for: decimal)
        lastValue = text
    }
}

расширение NumberFormatter {удобство init (numberStyle: Style) {self.init() self.numberStyle = numberStyle}}

extension Formatter {
    static let currency = NumberFormatter(numberStyle: .currency)
}
extension String {
    var digits: String { return filter { $0.isWholeNumber } }
    var decimal: Decimal { return Decimal(string: digits) ?? 0 }
}
extension Decimal {
    var number: NSDecimalNumber { return NSDecimalNumber(decimal: self) }
}

extension LosslessStringConvertible {
    var string: String { return .init(self) }
}

Ответ 3

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

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

Ответ 4

Мой окончательный код спасибо за вашу помощь

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($0)}.filter{ $0.toInt() != nil }.map{Character($0)} ) 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!)!)"

Ответ 5

Вот код для 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 из раскадровки или программно

Ответ 6

Просто для удовольствия: скопировал ответ Томаса (ему полные кредиты -and points-, пожалуйста) в файл для запуска в виде скрипта Swift 4.1 (с небольшими исправлениями):

dotnum.swift:

#!/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