Establecer la longitud máxima de caracteres de un UITextField en Swift

Sé que hay otros temas sobre esto, pero parece que no puedo encontrar la forma de implementarlo.

Estoy intentando limitar un UITextField a solo 5 caracteres

Preferiblemente alfanumérico y – y. y _

He visto este código

func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let maxLength = 4 let currentString: NSString = textField.text let newString: NSString = currentString.stringByReplacingCharactersInRange(range, withString: string) return newString.length <= maxLength } 

y

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let length = count(textField.text.utf16) + count(string.utf16) - range.length return length <= 10 } 

Simplemente no sé cómo implementarlo realmente o qué “campo de texto” debería cambiar para mi nombre personalizado UITextField

  1. Su controlador de vista debe cumplir con UITextFieldDelegate , como a continuación:

     class MyViewController: UIViewController, UITextFieldDelegate { } 
  2. Establezca el delegado de su campo de texto: myTextField.delegate = self

  3. Implemente el método en su controlador de vista: textField(_:shouldChangeCharactersInRange:replacementString:)

Todos juntos:

 class MyViewController: UIViewController,UITextFieldDelegate //set delegate to class @IBOutlet var mytextField: UITextField // textfield variable override func viewDidLoad() { super.viewDidLoad() mytextField.delegate = self //set delegate } func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { let maxLength = 4 let currentString: NSString = textField.text let newString: NSString = currentString.stringByReplacingCharactersInRange(range, withString: string) return newString.length < = maxLength } 

Para Swift 4

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let maxLength = 1 let currentString: NSString = textField.text! as NSString let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString return newString.length < = maxLength } 

Permitir que solo se ingrese un conjunto específico de caracteres en un campo de texto determinado

 func textField(textField: UITextField, shouldChangeCharactersInRange range: NSRange, replacementString string: String) -> Bool { var result = true if mytextField == numberField { if count(string) > 0 { let disallowedCharacterSet = NSCharacterSet(charactersInString: "0123456789.-").invertedSet let replacementStringIsLegal = string.rangeOfCharacterFromSet(disallowedCharacterSet) == nil result = replacementStringIsLegal } } return result } 

Cómo progtwigr un campo de texto de iOS que solo requiere entrada numérica con una longitud máxima

2017

Dic 2017. Swift 4.

Todo el código de ejemplo para esto está muy desactualizado.

Simplemente pegue lo siguiente en cualquier archivo Swift en su proyecto. (Puede asignarle un nombre al archivo, por ejemplo, “Handy.swift”)

Esto finalmente soluciona uno de los problemas más estúpidos en iOS:

enter image description here

Sus campos de texto ahora tienen un .maxLength .

Está completamente bien establecer ese valor en el guión gráfico o configurarlo en código.

 // simply have this in a file called, say, Handy.swift or TextUtility.swift import UIKit private var __maxLengths = [UITextField: Int]() extension UITextField { @IBInspectable var maxLength: Int { get { guard let l = __maxLengths[self] else { return 150 // (global default-limit. or just, Int.max) } return l } set { __maxLengths[self] = newValue addTarget(self, action: #selector(fix), for: .editingChanged) } } func fix(textField: UITextField) { let t = textField.text textField.text = t?.safelyLimitedTo(length: maxLength) } } extension String { func safelyLimitedTo(length n: Int)->String { if (self.count < = n) { return self } return String( Array(self).prefix(upTo: n) ) } } 

Es así de simple.


(Nota: "safelyLimitedTo # length" es solo una llamada que corta la longitud de un String. Casi todos los progtwigdores Swift tienen su propia función para eso, o bien, puedes usar el mío allí).

Solo por cierto, aquí hay un consejo similar e increíblemente útil relacionado con UIText View , https://stackoverflow.com/a/42333832/294884


Una versión más de KISS ...

Porque este problema es increíblemente molesto:

A menudo solo quieres un campo de texto especial en particular , que es simplemente limitado ("y eso es todo") a una cierta duración.

Por ejemplo, un código PIN es de cuatro caracteres, y eso es todo.

Es así de simple:

 class PinCodeEntry: UITextField { override func didMoveToSuperview() { super.didMoveToSuperview() addTarget(self, action: #selector(fixMe), for: .editingChanged) } @objc private func fixMe() { text = text?.safelyLimitedTo(length 4) } } 

¡Uf! Eso es todo al respecto.

De la misma manera que Steven Schmatz lo hizo pero usando Swift 3.0:

 //max Length func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let maxLength = 4 let currentString: NSString = textField.text! as NSString let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString return newString.length < = maxLength } 

Creo que la extensión es más útil para esto. Ver respuesta completa aquí

 private var maxLengths = [UITextField: Int]() // 2 extension UITextField { // 3 @IBInspectable var maxLength: Int { get { // 4 guard let length = maxLengths[self] else { return Int.max } return length } set { maxLengths[self] = newValue // 5 addTarget( self, action: #selector(limitLength), forControlEvents: UIControlEvents.EditingChanged ) } } func limitLength(textField: UITextField) { // 6 guard let prospectiveText = textField.text where prospectiveText.characters.count > maxLength else { return } let selection = selectedTextRange // 7 text = prospectiveText.substringWithRange( Range(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength)) ) selectedTextRange = selection } } 

Esta respuesta es para Swift 4, y es bastante directa con la capacidad de dejar atrás el espacio.

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return textField.text!.count < 10 || string == "" } 

Tengo algo que agregar a la respuesta de Aladin:

  1. Su controlador de vista debe cumplir con UITextFieldDelegate

     class MyViewController: UIViewController, UITextViewDelegate { } 
  2. Establezca el delegado de su campo de texto: para configurar el delegado, puede controlar el arrastre del campo de texto a su controlador de vista en el guión gráfico. Creo que esto es preferible a configurarlo en código

  3. Implemente el método en su controlador de vista: textField(_:shouldChangeCharactersInRange:replacementString:)

Otras soluciones publicadas anteriormente producen un ciclo de retención debido al mapa del campo de texto. Además, la propiedad maxLength debe ser anulable si no se establece en lugar de construcciones artificiales Int.max ; y el objective se establecerá varias veces si se cambia maxLength.

Aquí una solución actualizada para Swift4 con un mapa débil para evitar memory leaks y las otras correcciones

 private var maxLengths = NSMapTable(keyOptions: NSPointerFunctions.Options.weakMemory, valueOptions: NSPointerFunctions.Options.strongMemory) extension UITextField { var maxLength: Int? { get { return maxLengths.object(forKey: self)?.intValue } set { removeTarget(self, action: #selector(limitLength), for: .editingChanged) if let newValue = newValue { maxLengths.setObject(NSNumber(value: newValue), forKey: self) addTarget(self, action: #selector(limitLength), for: .editingChanged) } else { maxLengths.removeObject(forKey: self) } } } @IBInspectable var maxLengthInspectable: Int { get { return maxLength ?? Int.max } set { maxLength = newValue } } @objc private func limitLength(_ textField: UITextField) { guard let maxLength = maxLength, let prospectiveText = textField.text, prospectiveText.count > maxLength else { return } let selection = selectedTextRange text = String(prospectiveText[.. 

Doy una respuesta complementaria basada en @Frouo. Creo que su respuesta es la más bella. Porque es un control común que podemos reutilizar. Y no hay problema de fugas aquí.

  private var kAssociationKeyMaxLength: Int = 0 extension UITextField { @IBInspectable var maxLength: Int { get { if let length = objc_getAssociatedObject(self, &kAssociationKeyMaxLength) as? Int { return length } else { return Int.max } } set { objc_setAssociatedObject(self, &kAssociationKeyMaxLength, newValue, .OBJC_ASSOCIATION_RETAIN) self.addTarget(self, action: #selector(checkMaxLength), for: .editingChanged) } } //The method is used to cancel the check when use Chinese Pinyin input method. //Becuase the alphabet also appears in the textfield when inputting, we should cancel the check. func isInputMethod() -> Bool { if let positionRange = self.markedTextRange { if let _ = self.position(from: positionRange.start, offset: 0) { return true } } return false } func checkMaxLength(textField: UITextField) { guard !self.isInputMethod(), let prospectiveText = self.text, prospectiveText.count > maxLength else { return } let selection = selectedTextRange let maxCharIndex = prospectiveText.index(prospectiveText.startIndex, offsetBy: maxLength) text = prospectiveText.substring(to: maxCharIndex) selectedTextRange = selection } } 

Swift 4, simplemente use: public func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { return range.location < 10 }

Aquí hay una alternativa de Swift 3.2+ que evita la manipulación innecesaria de cadenas. En este caso, la longitud máxima es 10:

 func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let text = textField.text ?? "" return text.count - range.length + string.count < = 10 } 

Trabajando en Swift4

// PASO 1 establece UITextFieldDelegate

  class SignUPViewController: UIViewController , UITextFieldDelegate { @IBOutlet weak var userMobileNoTextFiled: UITextField! override func viewDidLoad() { super.viewDidLoad() 

// PASO 2 configurar delegado
userMobileNoTextFiled.delegate = self // establecer delegado}

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

// PASO 3 llamada func

  func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let maxLength = 10 // set your need let currentString: NSString = textField.text! as NSString let newString: NSString = currentString.replacingCharacters(in: range, with: string) as NSString return newString.length < = maxLength } } 

Solución simple sin usar delegado:

 TEXT_FIELD.addTarget(self, action: #selector(editingChanged(sender:)), for: .editingChanged) @objc private func editingChanged(sender: UITextField) { if let text = sender.text, text.count >= MAX_LENGHT { sender.text = String(text.dropLast(text.count - MAX_LENGHT)) return } }