Saltar al contenido

¿Cómo ingresar el formato de moneda en un campo de texto (de derecha a izquierda) usando Swift?

Contamos con tu ayuda para difundir nuestros ensayos acerca de las ciencias de la computación.

Para Swift 3. Ingrese el formato de moneda en un campo de texto (de derecha a izquierda)

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

Puede crear un campo de texto de moneda subclasificando UITextField. Agregue un destino para UIControlEvents .editingChanged. Agregue un método de selector para filtrar los dígitos de su campo de texto string. Después de filtrar todos los que no sean dígitos de su string puede formatear nuevamente su número usando NumberFormatter de la siguiente manera:

Xcode 11.5 • Swift 5.2 o posterior

import UIKit

class CurrencyField: UITextField 
    var decimal: Decimal  string.decimal / pow(10, Formatter.currency.maximumFractionDigits) 
    var maximum: Decimal = 999_999_999.99
    private var lastValue: String?
    var locale: Locale = .current 
        didSet 
            Formatter.currency.locale = locale
            sendActions(for: .editingChanged)
        
    
    override func willMove(toSuperview newSuperview: UIView?) 
        // you can make it a fixed locale currency if needed
        // self.locale = Locale(identifier: "pt_BR") // or "en_US", "fr_FR", etc
        Formatter.currency.locale = locale
        addTarget(self, action: #selector(editingChanged), for: .editingChanged)
        keyboardType = .numberPad
        textAlignment = .right
        sendActions(for: .editingChanged)
    
    override func deleteBackward() 
        text = string.digits.dropLast().string
        // manually send the editingChanged event
        sendActions(for: .editingChanged)
    
    @objc func editingChanged() 
        guard decimal <= maximum else 
            text = lastValue
            return
        
        text = decimal.currency
        lastValue = text
    


extension CurrencyField 
    var doubleValue: Double  (decimal as NSDecimalNumber).doubleValue 


extension UITextField 
     var string: String  text ?? "" 


extension NumberFormatter 
    convenience init(numberStyle: Style) 
        self.init()
        self.numberStyle = numberStyle
    


private extension Formatter 
    static let currency: NumberFormatter = .init(numberStyle: .currency)


extension StringProtocol where Self: RangeReplaceableCollection 
    var digits: Self  filter (.isWholeNumber) 


extension String 
    var decimal: Decimal  Decimal(string: digits) ?? 0 


extension Decimal 
    var currency: String  Formatter.currency.string(for: self) ?? "" 


extension LosslessStringConvertible 
    var string: String  .init(self) 


Ver controlador

class ViewController: UIViewController 

    @IBOutlet weak var currencyField: CurrencyField!
    override func viewDidLoad() 
        super.viewDidLoad()
        currencyField.addTarget(self, action: #selector(currencyFieldChanged), for: .editingChanged)
        currencyField.locale = Locale(identifier: "pt_BR") // or "en_US", "fr_FR", etc
    
    @objc func currencyFieldChanged() 
        print("currencyField:",currencyField.text!)
        print("decimal:", currencyField.decimal)
        print("doubleValue:",(currencyField.decimal as NSDecimalNumber).doubleValue, terminator: "nn")
    

Proyecto de muestra

Comencé con la respuesta de Leo Dabus (que no funcionó de la caja para mí) y en el proceso de tratar de simplificar y hacer que funcione terminé con esto, que creo que es bastante sencillo y limpio si lo digo yo mismo

class CurrencyTextField: UITextField 

    /// The numbers that have been entered in the text field
    private var enteredNumbers = ""

    private var didBackspace = false

    var locale: Locale = .current

    override init(frame: CGRect) 
        super.init(frame: frame)
        commonInit()
    

    required init?(coder: NSCoder) 
        super.init(coder: coder)
        commonInit()
    

    private func commonInit() 
        addTarget(self, action: #selector(editingChanged), for: .editingChanged)
    

    override func deleteBackward() 
        enteredNumbers = String(enteredNumbers.dropLast())
        text = enteredNumbers.asCurrency(locale: locale)
        // Call super so that the .editingChanged event gets fired, but we need to handle it differently, so we set the `didBackspace` flag first
        didBackspace = true
        super.deleteBackward()
    

    @objc func editingChanged() 
        defer 
            didBackspace = false
            text = enteredNumbers.asCurrency(locale: locale)
        

        guard didBackspace == false else  return 

        if let lastEnteredCharacter = text?.last, lastEnteredCharacter.isNumber 
            enteredNumbers.append(lastEnteredCharacter)
        
    


private extension Formatter 
    static let currency: NumberFormatter = 
        let formatter = NumberFormatter()
        formatter.numberStyle = .currency
        return formatter
    ()


private extension String 
    func asCurrency(locale: Locale) -> String? 
        Formatter.currency.locale = locale
        if self.isEmpty 
            return Formatter.currency.string(from: NSNumber(value: 0))
         else 
            return Formatter.currency.string(from: NSNumber(value: (Double(self) ?? 0) / 100))
        
    

Si eres capaz, tienes la habilidad dejar un post acerca de qué te ha impresionado de este tutorial.

¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)


Tags :

Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *