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.