es.davy.ai

Preguntas y respuestas de programación confiables

¿Tienes una pregunta?

Si tienes alguna pregunta, puedes hacerla a continuación o ingresar lo que estás buscando.

Formato Swift de entrada en porcentaje de forma “mientras-escribe”

Tengo un campo de texto que llama a un método para formatear la entrada como un porcentaje mientras se escribe.

cell.textField.addTarget(self, action: #selector(textChangedIntoPercent(sender:)), for: .editingChanged)

El método llamado:

@objc func textChangedIntoPercent (sender : UITextField) {

    if let amountString = sender.text?.percentInputFormatting() {
        sender.text = amountString
    }
}

El siguiente código funciona bien al ingresar números con el signo de porcentaje al final. Sin embargo, al usar la tecla retroceso, no se elimina nada, la cadena simplemente se regresa a sí misma y el último número no se elimina con la tecla retroceso. Si cambio la posición del cursor justo antes del signo de porcentaje, puedo eliminar los números.

func percentInputFormatting() -> String {

    var number: NSNumber!
    let formatter = NumberFormatter()
    formatter.numberStyle = .decimal
    formatter.maximumFractionDigits = 2
    formatter.minimumFractionDigits = 2

    var amountWithPrefix = self

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

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

    guard number != 0 as NSNumber else {
        return "0%"
    }

    return "\(formatter.string(from: number)!)" + "%"
}
Tags:  , , , ,

Answer

  1. Avatar for davy.ai

    Preguntas y Respuestas: Formato de Entrada de Porcentaje de iOS

    Pregunta

    Tengo un campo de texto que llama a un método para dar formato a la entrada como un porcentaje mientras se escribe. El siguiente código funciona bien al ingresar números con el signo % al final. Sin embargo, al usar el botón de retroceso, la cadena no se borra correctamente, sino que se devuelve a sí misma y el último número no se borra. Si cambio la posición del cursor justo antes del signo de porcentaje, puedo borrar los números. ¿Puede ayudarme a resolver este problema?

    cell.textField.addTarget(self, action: #selector(textChangedIntoPercent(sender:)), for: .editingChanged)
    
    @objc func textChangedIntoPercent (sender : UITextField) {
    
        if let amountString = sender.text?.percentInputFormatting() {
            sender.text = amountString
        }
    }
    
    func percentInputFormatting() -> String {
    
        var number: NSNumber!
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.maximumFractionDigits = 2
        formatter.minimumFractionDigits = 2
    
        var amountWithPrefix = self
    
        let regex = try! NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive)
        amountWithPrefix = regex.stringByReplacingMatches(in: amountWithPrefix, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, self.count), withTemplate: "")
    
        let double = (amountWithPrefix as NSString).doubleValue
        number = NSNumber(value: (double / 100))
    
        guard number != 0 as NSNumber else {
            return "0%"
        }
    
        return "\(formatter.string(from: number)!)" + "%"
    }
    

    Respuesta

    El problema con la implementación actual es que siempre agrega el signo de porcentaje al campo de texto al formatear la entrada. Esto dificulta el manejo de los eventos de retroceso.

    Una forma de resolver este problema es separar la cadena de entrada de la cadena formateada y solo agregar el signo de porcentaje a la cadena formateada. De esta manera, cuando se presiona el botón de retroceso, la cadena de entrada puede modificarse correctamente, sin afectar la cadena formateada.

    Aquí se muestra una implementación actualizada de la función percentInputFormatting():

    func percentInputFormatting() -> String {
    
        var number: NSNumber!
        let formatter = NumberFormatter()
        formatter.numberStyle = .decimal
        formatter.maximumFractionDigits = 2
        formatter.minimumFractionDigits = 2
    
        var inputString = self
    
        let regex = try! NSRegularExpression(pattern: "[^0-9]", options: .caseInsensitive)
        inputString = regex.stringByReplacingMatches(in: inputString, options: NSRegularExpression.MatchingOptions(rawValue: 0), range: NSMakeRange(0, self.count), withTemplate: "")
    
        let double = (inputString as NSString).doubleValue
        number = NSNumber(value: (double / 100))
    
        guard number != 0 as NSNumber else {
            return "0%"
        }
    
        let formattedString = "\(formatter.string(from: number)!)" + "%"
    
        if let lastChar = self.last, lastChar == "%" {
            // Incluir el signo de porcentaje en la cadena de entrada
            inputString += "%"
        }
    
        return formattedString
    }
    

    En esta implementación, la cadena de entrada es la cadena original sin caracteres no numéricos. La cadena formattedString es el valor de entrada formateado como un porcentaje, con el signo de porcentaje agregado al final.

    Si el último carácter en la cadena original es un signo de porcentaje, la cadena de entrada se modifica para incluir el signo de porcentaje. Esto asegura que el botón de retroceso funcione correctamente.

    Con esta implementación, la función textChangedIntoPercent() puede permanecer igual. El único cambio necesario es actualizar la firma del método para incluir el último parámetro:

    @objc func textChangedIntoPercent (sender : UITextField, range: NSRange, string: String) {
    
        let oldText = sender.text ?? ""
        let newText = (oldText as NSString).replacingCharacters(in: range, with: string)
    
        if let amountString = newText.percentInputFormatting() {
            sender.text = amountString
        }
    }
    

    Al pasar los parámetros range y string del método delegado shouldChangeCharactersIn del campo de texto a la función textChangeIntoPercent, puede manejar correctamente los eventos de retroceso y otros eventos de entrada de texto.

Comments are closed.