length ios string swift uitextfield character

ios - max length uitextfield swift



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

Sé que hay otros temas sobre esto, pero parece que no puedo encontrar cómo implementarlo.

Estoy tratando de 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 por mi UITextField personalizado


Dic. 2017. Swift 4.

Tenga cuidado de que gran parte del código de ejemplo que verá en línea con respecto a este problema está muy desactualizado .

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:

Sus campos de texto ahora tienen un .maxLength .

Está completamente bien establecer ese valor en el guión gráfico durante el desarrollo o establecerlo en código mientras la aplicación se está ejecutando.

// simply have this in any Swift file, say, Handy.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?.prefix(maxLength) } }

Es así de simple.

Nota al pie: en estos días para truncar una String manera segura, simplemente .prefix(n)

Una versión única aún más simple ...

Lo anterior corrige todos los campos de texto en su proyecto.

Si solo desea que un campo de texto en particular se limite a decir "4", y eso es todo ...

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

¡Uf! Eso es todo al respecto.

(Solo por cierto, aquí hay un consejo muy útil similar relacionado con UIText View , https://.com/a/42333832/294884 )


  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 dado

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 programar un campo de texto de iOS que solo toma entrada numérica con una longitud máxima


Aquí hay una alternativa a 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 }


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

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<String.Index>(prospectiveText.startIndex ..< prospectiveText.startIndex.advancedBy(maxLength)) ) selectedTextRange = selection } }


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 }


Doy una respuesta complementaria basada en @Frouo. Creo que su respuesta es la forma más bella. Porque es un control común que podemos reutilizar. Y no hay ningún problema de fuga 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 } }


Esta respuesta es para Swift 4, y es bastante sencilla con la capacidad de dejar retroceder el espacio.

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


Mi versión Swift 4 de shouldChangeCharactersIn

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { guard let preText = textField.text as NSString?, preText.replacingCharacters(in: range, with: string).count <= MAX_TEXT_LENGTH else { return false } return true }


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

Aquí una solución actualizada para Swift4 con un mapa débil para evitar pérdidas de memoria y otras correcciones

private var maxLengths = NSMapTable<UITextField, NSNumber>(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[..<prospectiveText.index(from: maxLength)]) selectedTextRange = selection } }


Simplemente verifique con el número de caracteres en la cadena

  1. Agregar un delegado para ver el controlador y el delegado

class YorsClassName : UITextFieldDelegate { }

  1. verifique la cantidad de caracteres permitidos para el campo de texto

func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { if textField.text?.count == 1 { return false } return true }

Nota: Aquí verifiqué solo los caracteres permitidos en textField



Tengo algo que agregar a la respuesta de Aladin:

  1. Su controlador de vista debe cumplir con UITextFieldDelegate

    class MyViewController: UIViewController, UITextViewDelegate { }

  2. Configure el delegado de su campo de texto: para configurar el delegado, puede controlar el arrastre desde el 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:)


Utilizo este paso, primero Establecer delegado texfield en viewdidload.

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

y luego shouldChangeCharactersIn después de incluir UITextFieldDelegate.

extension viewController: UITextFieldDelegate { func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool { let newLength = (textField.text?.utf16.count)! + string.utf16.count - range.length if newLength <= 8 { return true } else { return false } } }


actualización para esta respuesta Fattie

Gracias

extension UITextField { /// Runtime key private struct AssociatedKeys { /// max lenght key static var maxlength: UInt8 = 0 /// temp string key static var tempString: UInt8 = 0 } /// Limit the maximum input length of the textfiled @IBInspectable var maxLength: Int { get { return objc_getAssociatedObject(self, &AssociatedKeys.maxlength) as? Int ?? 0 } set { objc_setAssociatedObject(self, &AssociatedKeys.maxlength, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) addTarget(self, action: #selector(handleEditingChanged(textField:)), for: .editingChanged) } } /// temp string private var tempString: String? { get { return objc_getAssociatedObject(self, &AssociatedKeys.tempString) as? String } set { objc_setAssociatedObject(self, &AssociatedKeys.tempString, newValue, objc_AssociationPolicy.OBJC_ASSOCIATION_RETAIN_NONATOMIC) } } /// When the text changes, process the amount of text in the input box so that its length is within the controllable range. @objc private func handleEditingChanged(textField: UITextField) { /// Special Processing for Chinese Input Method guard markedTextRange == nil else { return } if textField.text?.count == maxLength { /// SET lastQualifiedString where text length == max lenght tempString = textField.text } else if textField.text?.count ?? 0 < maxLength { /// clear lastQualifiedString when text lengeht > maxlength tempString = nil } /// keep current text range in arcgives let archivesEditRange: UITextRange? if textField.text?.count ?? 0 > maxLength { /// if text length > maxlength,remove last range,to move to -1 postion. let position = textField.position(from: safeTextPosition(selectedTextRange?.start), offset: -1) ?? textField.endOfDocument archivesEditRange = textField.textRange(from: safeTextPosition(position), to: safeTextPosition(position)) } else { /// just set current select text range archivesEditRange = selectedTextRange } /// main handle string max length textField.text = tempString ?? String((textField.text ?? "").prefix(maxLength)) /// last config edit text range textField.selectedTextRange = archivesEditRange } /// get safe textPosition private func safeTextPosition(_ optionlTextPosition: UITextPosition?) -> UITextPosition { /* beginningOfDocument -> The end of the the text document. */ return optionlTextPosition ?? endOfDocument } }


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 } }


Swift 4, simplemente use:

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


Trabajando en Swift4

// PASO 1 establece UITextFieldDelegate

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

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

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 llamar a 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 } }