Longitud máxima UITextField


Cuando he probado ¿Cómo establecer el número máximo de caracteres que se pueden introducir en un UITextField utilizando swift?, vi que si uso los 10 caracteres, no puedo borrar el carácter también.

Lo único que puedo hacer es cancelar la operación (eliminar todos los caracteres juntos).

¿Alguien sabe cómo no bloquear el teclado (para que no pueda agregar otras letras/símbolos/números, pero puedo usar el retroceso)?

Author: Community, 2014-08-10

14 answers

Para Swift 3, pruebe la siguiente implementación de textField(_:shouldChangeCharactersIn:replacementString:) eso es parte del protocolo UITextFieldDelegate:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let text = textField.text else { return true }
    let newLength = text.characters.count + string.characters.count - range.length
    return newLength <= 10 // Bool
}

De acuerdo con sus necesidades, sin embargo, puede preferir esta implementación (vea Cadenas en Swift 2 para más detalles):

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
    guard let text = textField.text else { return true }

    let newLength = text.utf16.count + string.utf16.count - range.length
    return newLength <= 10 // Bool
}

El siguiente código muestra cómo implementarlo en un UIViewController:

import UIKit

class ViewController: UIViewController, UITextFieldDelegate {

    @IBOutlet weak var textField: UITextField! // Link this to a UITextField in your storyboard
    let limitLength = 10

    override func viewDidLoad() {
        super.viewDidLoad()
        textField.delegate = self
    }

    func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        guard let text = textField.text else { return true }
        let newLength = text.characters.count + string.characters.count - range.length
        return newLength <= limitLength
    }

}
 205
Author: Imanou Petit,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-04-17 21:01:29

Lo hago así:

func checkMaxLength(textField: UITextField!, maxLength: Int) {
    if (countElements(textField.text!) > maxLength) {
        textField.deleteBackward()
    }
}

El código funciona para mí. Pero trabajo con storyboard. En Storyboard I añadir una acción para el campo de texto en el controlador de vista en edición cambiado.

 41
Author: Martin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-10-15 10:34:14

Actualización para Swift 4

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
     guard let text = textField.text else { return true }
     let newLength = text.count + string.count - range.length
     return newLength <= 10
}
 14
Author: Shan Ye,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-11-03 09:31:44

Agrega más detalles de @Martin respuesta

// linked your button here
@IBAction func mobileTFChanged(sender: AnyObject) {
    checkMaxLength(sender as! UITextField, maxLength: 10)
}

// linked your button here
@IBAction func citizenTFChanged(sender: AnyObject) {
    checkMaxLength(sender as! UITextField, maxLength: 13)
}

func checkMaxLength(textField: UITextField!, maxLength: Int) {
    // swift 1.0
    //if (count(textField.text!) > maxLength) {
    //    textField.deleteBackward()
    //}
    // swift 2.0
    if (textField.text!.characters.count > maxLength) {
        textField.deleteBackward()
    }
}
 13
Author: Sruit A.Suk,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-07-10 19:43:42
func checkMaxLength(textField: UITextField!, maxLength: Int) {
        if (textField.text!.characters.count > maxLength) {
            textField.deleteBackward()
        }
}

Un pequeño cambio para IOS 9

 6
Author: Jeremy Andrews,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-10-06 06:39:22

Swift 3

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

            let nsString = NSString(string: textField.text!)
            let newText = nsString.replacingCharacters(in: range, with: string)
            return  newText.characters.count <= limitCount
    }
 5
Author: Basil Mariano,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-03-02 05:38:26

En Swift 4

10 Caracteres límite para el campo de texto y permitir eliminar(retroceso)

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
        if textField ==  userNameFTF{
            let char = string.cString(using: String.Encoding.utf8)
            let isBackSpace = strcmp(char, "\\b")
            if isBackSpace == -92 {
                return true
            }
            return textField.text!.count <= 9
        }
        return true
    }
 4
Author: Sai kumar Reddy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-27 12:35:01

Publiqué una solución usando IBInspectable, por lo que puede cambiar el valor de longitud máxima tanto en interface builder como mediante programación. Compruébalo aquí

 3
Author: Frouo,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 12:18:01

Si desea sobrescribir la última letra:

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {

    if range.location > 9 {
        textField.text?.removeLast()
    }

    return true
}
 2
Author: maxwell,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2018-01-17 12:01:25

Tenga cuidado con el error deshacer para UITextField mencionado en este post: Establezca la longitud máxima de caracteres de un UITextField

Así es como lo arreglas en swift

if(range.length + range.location > count(textField.text)) {
        return false;
}
 1
Author: Horatio,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-05-23 11:47:13
Here is my version of code. Hope it helps!

    func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool {
        let invalidCharacters = NSCharacterSet(charactersInString: "0123456789").invertedSet

        if let range = string.rangeOfCharacterFromSet(invalidCharacters, options: nil, range:Range<String.Index>(start: string.startIndex, end: string.endIndex))
        {
            return false
        }

        if (count(textField.text) > 10  && range.length == 0)
        {
            self.view.makeToast(message: "Amount entry is limited to ten digits", duration: 0.5, position: HRToastPositionCenter)
            return false
        }
        else
        {

        }

        return true
    }
 1
Author: A.G,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2015-11-03 04:35:26

He estado usando este protocolo / extensión en una de mis aplicaciones, y es un poco más legible. Me gusta cómo reconoce los espacios atrás y te dice explícitamente cuándo un personaje es un espacio atrás.

Algunas cosas a considerar:

1.Lo que implementa esta extensión de protocolo necesita especificar un límite de caracteres. Ese suele ser tu ViewController, pero podrías implementar character limit como una propiedad computada y devolver algo más, por ejemplo un límite de caracteres en uno de sus modelos.

2. Tendrá que llamar a este método dentro del método delegado shouldChangeCharactersInRange de su campo de texto. De lo contrario, no podrá bloquear la entrada de texto devolviendo false, etc.

3. Es probable que desee permitir que los caracteres de retroceso a través. Es por eso que agregué la función extra para detectar backspaces. Su método shouldChangeCharacters puede verificar esto y devolver 'true' temprano para que siempre permita espacios traseros.

protocol TextEntryCharacterLimited{
    var characterLimit:Int { get } 
}

extension TextEntryCharacterLimited{

    func charactersInTextField(textField:UITextField, willNotExceedCharacterLimitWithReplacementString string:String, range:NSRange) -> Bool{

        let startingLength = textField.text?.characters.count ?? 0
        let lengthToAdd = string.characters.count
        let lengthToReplace = range.length

        let newLength = startingLength + lengthToAdd - lengthToReplace

        return newLength <= characterLimit

    }

    func stringIsBackspaceWith(string:String, inRange range:NSRange) -> Bool{
        if range.length == 1 && string.characters.count == 0 { return true }
        return false
    }

}

Si alguno de ustedes está interesado, tengo un repositorio de Github donde he tomado parte de este comportamiento de límite de caracteres y lo he puesto en un marco de trabajo de iOS. Hay un protocolo que puedes implementar para obtener una visualización de límite de caracteres similar a Twitter que te muestra lo lejos que has llegado por encima del límite de caracteres.

CharacterLimited Framework en Github

 1
Author: Theo Bendixson,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2016-09-10 16:41:19

Dado que los delegados son una relación de 1 a 1 y es posible que desee usarla en otro lugar por otras razones, me gusta restringir la longitud del campo de texto agregando este código dentro de su configuración:

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)!
        setup()
    }

    required override init(frame: CGRect) {
        super.init(frame: frame)
        setup()
    }

    func setup() {

        // your setup...

        setMaxLength()
    }

    let maxLength = 10

    private func setMaxLength() {
            addTarget(self, action: #selector(textfieldChanged(_:)), for: UIControlEvents.editingChanged)
        }

        @objc private func textfieldChanged(_ textField: UITextField) {
            guard let text = text else { return }
            let trimmed = text.characters.prefix(maxLength)
            self.text = String(trimmed)

        }
 1
Author: MQLN,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2017-10-13 01:18:58

Debe verificar si la cadena existente más la entrada es mayor que 10.

   func textField(textField: UITextField!,shouldChangeCharactersInRange range: NSRange,    replacementString string: String!) -> Bool {
      NSUInteger newLength = textField.text.length + string.length - range.length;
      return !(newLength > 10)
   }
 -2
Author: bhzag,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/ajaxhispano.com/template/agent.layouts/content.php on line 61
2014-08-09 23:16:09